<> <> <> DIRECTORY Atom USING [MakeAtom], IO USING [PutChar, PutRope, STREAM], IPBasic USING [Any, ComposedOp, Identifier, Index, Integer, Marker, nullIndex, nullMarker, Number, Operator, OperatorRep, PrimitiveOp, SaveType, Vec, Vector, VectorShape], IPControl USING [], IPConvert USING [IntToNumber], IPEncoding USING [GetInt, GetToken, GetReal, GetRope, GetStartingIndex, OpenReader, Reader, Token], IPErrors USING [AppearanceError, AppearanceErrorType, AppearanceWarning, AppearanceWarningType, Bug, Error, MasterError, MasterErrorType, MasterWarning, MasterWarningType, RopeFromError], IPExec USING [], IPImagerOps USING [Init, Restore, Save], IPLimits USING [topFrameSize], IPPrimitive USING [Apply], IPStack USING [Count, Init, PopInteger, PopMark, PopToMark, PushIdentifier, PushInteger, PushNumber, PushReal, PushVector], IPState USING [Context, ContextRep, nullContextRep, Skeleton, SkeletonRep, State, StateRep], IPVector USING [CopyVec, NewVec, VectorToVec], IPWritten USING [RopeFromOp], Rope USING [ROPE, Translate]; IPExecImpl: CEDAR PROGRAM IMPORTS Atom, IO, IPConvert, IPEncoding, IPErrors, IPImagerOps, IPPrimitive, IPStack, IPVector, IPWritten, Rope EXPORTS IPExec, IPControl, IPBasic = BEGIN OPEN IPEncoding, IPState, IPBasic; ROPE: TYPE = Rope.ROPE; State: TYPE = IPState.State; StateRep: PUBLIC TYPE = IPState.StateRep; -- export to IPBasic Master: TYPE = IPEncoding.Reader; MarkRecovery: ERROR = CODE; Frame: PROC[self: State] RETURNS[Vec] = { f: Vec = self.context.frame; RETURN[IF f#NIL THEN IPVector.CopyVec[f] ELSE self.context.initialFrame] }; ReadonlyFrame: PROC[context: Context] RETURNS[Vec] = INLINE { RETURN[ IF context.frame#NIL THEN context.frame ELSE context.initialFrame] }; MutableFrame: PROC[context: Context] RETURNS[Vec] = INLINE { RETURN[ IF context.frame#NIL THEN context.frame ELSE context.frame _ IPVector.CopyVec[context.initialFrame]] }; FGet: PUBLIC PROC[self: State, n: Integer] RETURNS[Any] = { frame: Vec = ReadonlyFrame[self.context]; shape: VectorShape = frame.shape; IF n IN[shape.l..shape.l+shape.n) THEN RETURN[frame[n-shape.l]] ELSE ERROR IPErrors.MasterError[BoundsFault]; }; FSet: PUBLIC PROC[self: State, x: Any, n: Integer] = { frame: Vec = MutableFrame[self.context]; shape: VectorShape = frame.shape; IF n IN[shape.l..shape.l+shape.n) THEN frame[n-shape.l] _ x ELSE ERROR IPErrors.MasterError[BoundsFault]; }; MakeCO: PUBLIC PROC[self: State, f: Vector] RETURNS[Operator] = { frame: Vec = IPVector.VectorToVec[f]; index: Index = SkipBody[self]; RETURN[NEW[OperatorRep[composed] _ [composed[start: index, initialFrame: frame]]]]; }; MakeSimpleCO: PUBLIC PROC[self: State] RETURNS[Operator] = { frame: Vec = Frame[self]; -- copy the current frame index: Index = SkipBody[self]; RETURN[NEW[OperatorRep[composed] _ [composed[start: index, initialFrame: frame]]]]; }; Do: PUBLIC PROC[self: State, o: Operator, sv: SaveType _ nil] = { WITH o SELECT FROM op: ComposedOp => { caller: Context = self.context; savedPC: Index = self.pc; self.pc _ op.start; -- set the pc to the beginning of the operator's body [] _ CallBody[self, op.initialFrame, sv ! MarkRecovery => self.pc _ savedPC]; self.pc _ savedPC; -- restore caller's pc IF self.context#caller THEN ERROR IPErrors.Bug; }; ENDCASE => ERROR IPErrors.MasterError[Unimplemented]; }; DoBody: PUBLIC PROC[self: State, f: Vector, sv: SaveType _ nil] = { frame: Vec = IPVector.VectorToVec[f]; [] _ CallBody[self, frame, sv]; }; DoSimpleBody: PUBLIC PROC[self: State, sv: SaveType _ nil] = { frame: Vec = Frame[self]; [] _ CallBody[self, frame, sv]; }; If: PUBLIC PROC[self: State, b: BOOL] = { IF b THEN DoSimpleBody[self] ELSE [] _ SkipBody[self]; }; IfCopy: PUBLIC PROC[self: State, testCopy: Operator] = { ERROR IPErrors.MasterError[Unimplemented]; }; <<>> CopyNumberAndName: PUBLIC PROC[self: State] RETURNS[copyNumber: Number, copyName: Identifier] = { ERROR; }; <<>> <> <<2.4.1 Errors>> <> <> <> <> <<>> <> NewMark: PROC[self: State] RETURNS[Marker] = { last: Marker = self.lastMark; IF last [] _ PopContext[self]; IF sv#nil THEN IPImagerOps.Save[self, sv=saveAll]; DO token: Token = master.GetToken[self.pc]; -- fetch the next token self.pc _ token.next; IF token.op=endBody THEN EXIT ELSE { DoToken[self, token ! IPErrors.MasterError => { LogError[self, [Me[type]], token]; self.pc _ token.index; GOTO Recover }; IPErrors.MasterWarning => { LogError[self, [Mw[type]], token]; RESUME }; IPErrors.AppearanceError => { LogError[self, [Ae[type]], token]; RESUME }; IPErrors.AppearanceWarning => { LogError[self, [Aw[type]], token]; RESUME }; MarkRecovery => GOTO Recover; ]; EXITS Recover => { marker: Marker = PopToMarkOnCallStack[self]; IF marker=self.context.mark THEN { IF SkipToUnmark0OrEndOfBody[self] THEN { -- press on -- } ELSE GOTO Exit; -- marked by this context, but unmark0 not found } ELSE { SkipToEndOfBody[self]; GOTO Exit }; -- not marked by this context }; }; REPEAT Exit => error _ TRUE; ENDLOOP; IF sv#nil THEN IPImagerOps.Restore[self]; }; finalFrame _ PopContext[self]; IF error THEN ERROR MarkRecovery; }; DoToken: PROC[self: State, token: Token] = { SELECT token.type FROM op => IPPrimitive.Apply[self, token.op]; number => IPStack.PushNumber[self, IPConvert.IntToNumber[token.number]]; int => IPStack.PushNumber[self, IPConvert.IntToNumber[self.master.GetInt[token]]]; rational, real => IPStack.PushReal[self, self.master.GetReal[token]]; identifier => IPStack.PushIdentifier[self, MakeID[self.master.GetRope[token]]]; string, largeVec => IPStack.PushVector[self, self.master.GetRope[token]]; comment => { }; ENDCASE => ERROR IPErrors.Bug; -- unexpected token type }; MakeID: PUBLIC PROC[rope: ROPE] RETURNS[Identifier] = { LowerCase: PROC[c: CHAR] RETURNS[CHAR] = { RETURN[IF c IN['A..'Z] THEN (c-'A)+'a ELSE c] }; RETURN[Atom.MakeAtom[Rope.Translate[base: rope, translator: LowerCase]]]; }; SetErrorLog: PUBLIC PROC[self: State, log: IO.STREAM] = { self.log _ log; }; LogError: PROC[self: State, error: IPErrors.Error, token: Token] = { log: IO.STREAM = self.log; rope: Rope.ROPE = IPErrors.RopeFromError[error]; IF log#NIL THEN { log.PutRope[rope]; IF token.op#nil THEN { log.PutRope[" -- "]; log.PutRope[IPWritten.RopeFromOp[token.op]]; }; log.PutChar['\n]; }; }; BeginBody: PROC[self: State] RETURNS[Index] = { token: Token = Fetch[self]; IF token.op=beginBody THEN RETURN[token.index] ELSE { self.pc _ token.index; ERROR IPErrors.MasterError[MissingBody] }; }; SkipBody: PROC[self: State] RETURNS[Index] = { index: Index = BeginBody[self]; SkipToEndOfBody[self]; RETURN[index]; }; SkipToEndOfBody: PROC[self: State] = { DO token: Token = Fetch[self]; SELECT token.op FROM beginBody => SkipToEndOfBody[self]; endBody => EXIT; ENDCASE; ENDLOOP; }; SkipToUnmark0OrEndOfBody: PROC[self: State] RETURNS[BOOL] = { DO token: Token = Fetch[self]; SELECT token.op FROM unmark0 => { self.pc _ token.index; RETURN[TRUE] }; beginBody => SkipToEndOfBody[self]; endBody => EXIT; ENDCASE; ENDLOOP; RETURN[FALSE]; }; initialTopFrame: Vec = IPVector.NewVec[[l: 0, n: IPLimits.topFrameSize]]; OpenMaster: PUBLIC PROC[name: ROPE] RETURNS[State] = { master: Master = OpenReader[name]; self: State = NEW[StateRep _ [master: NIL, skeleton: NIL, pc: 0, stack: NIL, topFrame: NIL, context: NIL, lastMark: nullMarker, imager: NIL]]; self.master _ master; self.pc _ master.GetStartingIndex[]; IPStack.Init[self, 1000]; IPImagerOps.Init[self]; self.skeleton _ GetSkeleton[self]; IF self.skeleton.size<2 THEN ERROR IPErrors.MasterError[MalformedSkeleton]; self.topFrame _ DoPreamble[self, initialTopFrame]; RETURN[self]; }; PageCount: PUBLIC PROC[self: State] RETURNS[NAT] = { RETURN[self.skeleton.size-1]; }; DoPreamble: PROC[self: State, frame: Vec] RETURNS[Vec] = { self.pc _ self.skeleton[0].body; -- beginning of the preamble RETURN[CallBody[self, frame, saveAll]]; }; DoPage: PUBLIC PROC[self: State, n: NAT] = { self.pc _ self.skeleton[n].body; -- beginning of the page body [] _ CallBody[self, self.topFrame, saveAll]; }; GetSkeleton: PROC[self: State] RETURNS[Skeleton] = { token: Token = Fetch[self]; SELECT token.op FROM beginBody => { IPStack.PushInteger[self, token.index]; -- instructions body SkipToEndOfBody[self]; IF Fetch[self].op=beginBlock THEN GetBlock[self] ELSE ERROR IPErrors.MasterError[MalformedSkeleton]; }; beginBlock => { IPStack.PushInteger[self, nullIndex]; -- no instructions GetBlock[self]; }; ENDCASE => ERROR IPErrors.MasterError[MalformedSkeleton]; { count: NAT = IPStack.Count[self]; size: NAT = count/2; skeleton: Skeleton = NEW[SkeletonRep[size]]; FOR i: NAT DECREASING IN[0..size) DO body: Index = IPStack.PopInteger[self]; instructions: Index = IPStack.PopInteger[self]; skeleton[i] _ [instructions: instructions, body: body]; ENDLOOP; RETURN[skeleton]; }; }; GetBlock: PROC[self: State] = { IPStack.PushInteger[self, SkipBody[self]]; -- preamble DO token: Token = Fetch[self]; SELECT token.op FROM endBlock => EXIT; pageInstructions => { IPStack.PushInteger[self, SkipBody[self]]; -- page instructions body IPStack.PushInteger[self, SkipBody[self]]; -- page body }; beginBody => { IPStack.PushInteger[self, nullIndex]; -- no page instructions IPStack.PushInteger[self, token.index]; -- page body SkipToEndOfBody[self]; }; ENDCASE => ERROR IPErrors.MasterError[MalformedSkeleton]; ENDLOOP; }; END.