<> <> <> <<>> DIRECTORY Commander USING [CommandProc, Register], EditedStream USING [DeliverWhenProc, Rubout, SetDeliverWhen], FS USING [ExpandName], IO USING [GetChar, int, Put1, PutRope, real, refAny, STREAM], List USING [AList, Assoc, PutAssoc], Process USING [Detach], ProcessProps USING [AddPropList, GetPropList], RefText USING [AppendChar], Rope USING [Concat, FromRefText, ROPE, Size, Substr], TJaM USING [Any, AtomFromRope, CommandProc, CvX, Def, ExecuteAtom, ExecuteRope, Exit, Frame, LineComplete, NewFrame, Number, Pop, Register, RopeFromAtom, Stop], ViewerIO USING [CreateViewerStreams]; TJaMTest: CEDAR PROGRAM IMPORTS Commander, EditedStream, FS, IO, List, Process, ProcessProps, RefText, Rope, TJaM, ViewerIO ~ BEGIN OPEN TJaM; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; Ref: TYPE ~ REF Rep; Rep: TYPE ~ RECORD[ frame: Frame, in, out: STREAM _ NIL ]; refKey: ATOM ~ $JaMInterpreter; AddProps: PROC[ref: Ref, wDir: ROPE, inner: PROC] ~ { propList: List.AList _ NIL; propList _ List.PutAssoc[key: refKey, val: ref, aList: propList]; propList _ List.PutAssoc[key: $WorkingDirectory, val: wDir, aList: propList]; ProcessProps.AddPropList[propList, inner]; }; GetRef: PROC RETURNS[Ref] ~ { propList: List.AList ~ ProcessProps.GetPropList[]; val: REF ~ List.Assoc[key: refKey, aList: propList]; WITH val SELECT FROM ref: Ref => RETURN[ref] ENDCASE; RETURN[NIL]; }; JaMDeliverWhen: EditedStream.DeliverWhenProc ~ { ok: BOOL _ FALSE; IF char='\n THEN { rope: ROPE ~ Rope.FromRefText[buffer]; ok _ LineComplete[rope]; }; RETURN[appendChar: TRUE, activate: ok]; }; promptKey: ATOM ~ AtomFromRope[".prompt"]; promptRope: ROPE ~ "(*) .print"; promptVal: Any ~ CvX[promptRope]; printKey: ATOM ~ AtomFromRope[".print"]; quitKey: ATOM ~ AtomFromRope[".quit"]; ApplyPrint: PROC[frame: Frame] ~ { self: Ref ~ GetRef[]; x: REF ~ Pop[frame]; WITH x SELECT FROM x: Number => WITH n: x SELECT FROM int => IO.Put1[self.out, IO.int[n.int]]; real => IO.Put1[self.out, IO.real[n.real]]; ENDCASE => ERROR; x: ATOM => IO.PutRope[self.out, RopeFromAtom[x]]; x: ROPE => IO.PutRope[self.out, x]; ENDCASE => IO.Put1[self.out, IO.refAny[x]]; }; Quit: ERROR ~ CODE; ApplyQuit: PROC[frame: Frame] ~ { ERROR Quit; }; AppendLine: PROC[text: REF TEXT, stream: STREAM] RETURNS[REF TEXT] ~ { DO char: CHAR ~ IO.GetChar[stream]; text _ RefText.AppendChar[text, char]; IF char='\n THEN EXIT; ENDLOOP; RETURN[text]; }; JaMInterpreterProcess: PROC[self: Ref, wDir: ROPE] ~ { frame: Frame ~ self.frame; inner: PROC ~ { buffer: REF TEXT ~ NEW[TEXT[500]]; DO command: ROPE _ NIL; text: REF TEXT _ buffer; text.length _ 0; ExecuteAtom[frame, promptKey]; { DO text _ AppendLine[text, self.in ! EditedStream.Rubout => GOTO Del]; command _ Rope.FromRefText[text]; IF LineComplete[command] THEN EXIT; ENDLOOP; ExecuteRope[frame: frame, rope: command ! Stop => CONTINUE; Exit => RESUME; Quit => EXIT; ]; EXITS Del => IO.PutRope[self.out, " -- \n"]; }; ENDLOOP; }; EditedStream.SetDeliverWhen[self.in, JaMDeliverWhen]; Register[frame, AtomFromRope[".print"], ApplyPrint]; Register[frame, AtomFromRope[".quit"], ApplyQuit]; Def[frame, promptKey, promptVal]; AddProps[self, wDir, inner]; }; GetWorkingDirectory: PROC RETURNS[ROPE] ~ { dummyName: ROPE ~ "*"; fullFName: ROPE ~ FS.ExpandName[dummyName].fullFName; RETURN[Rope.Substr[base: fullFName, len: Rope.Size[fullFName]-Rope.Size[dummyName]]]; }; JaMCommand: Commander.CommandProc ~ { self: Ref ~ NEW[Rep _ [frame: NewFrame[]]]; wDir: ROPE ~ GetWorkingDirectory[]; viewerName: ROPE ~ Rope.Concat["TJaM ", wDir]; [in: self.in, out: self.out] _ ViewerIO.CreateViewerStreams[viewerName]; TRUSTED { Process.Detach[FORK JaMInterpreterProcess[self, wDir]] }; }; Commander.Register["TJaM", JaMCommand]; END.