DIRECTORY Ascii, Atom, Commander, IO, ProcessProps, Rope, RuntimeError, Scheme, SchemePrivate, SchemeStart, SchemeSys, UXIO; SchemeSysImpl: CEDAR PROGRAM IMPORTS Atom, Commander, IO, ProcessProps, Rope, RuntimeError, Scheme, UXIO EXPORTS SchemeSys, SchemeStart ~ BEGIN OPEN Scheme; ROPE: TYPE ~ Rope.ROPE; savedEnv: Environment ¬ NIL; RunScheme: PUBLIC --SchemeStart-- PROC ~ { env: Environment ¬ savedEnv; in: IO.STREAM ¬ UXIO.CreateStandardStream[input]; out: IO.STREAM ¬ UXIO.CreateStandardStream[output]; Inner: PROC ~ { IF env = NIL THEN { savedEnv ¬ env ¬ NewEnvironmentStructure[] } ELSE { InitializeEnvironmentStructure[env] }; ReadEvalPrintLoop[in, out, env]; SELECT IO.PeekChar[in] FROM Ascii.LF, Ascii.CR => [] ¬ IO.GetChar[in]; ENDCASE; }; DoWithPorts[in: in, out: out, proc: Inner]; }; OpenedStream: TYPE ~ RECORD [s: IO.STREAM ¬ NIL, fullFName: ROPE ¬ NIL, shortFName: ROPE, searchRules: LIST OF ROPE]; IsFileStream: PUBLIC PROC [stream: IO.STREAM] RETURNS [BOOL] ~ { RETURN [FALSE] }; GetFileNameForStream: PUBLIC PROC [stream: IO.STREAM] RETURNS [ROPE] ~ { RETURN [NIL]; }; GetFileCreateDateForStream: PUBLIC PROC [stream: IO.STREAM] RETURNS [ROPE] ~ { RETURN [NIL]; }; CheckForAbort: PUBLIC PROC ~ { }; GetStdStream: SIGNAL [inP: BOOL] RETURNS [IO.STREAM] ~ CODE; GetPort: PUBLIC PROC [param: REF, in: BOOL] RETURNS [IO.STREAM] ~ { IF param = undefined THEN { stream: IO.STREAM ¬ GetStdStream[inP: in]; RETURN [stream] } ELSE RETURN [ThePort[param]]; }; SetPortSignal: SIGNAL [newPort: IO.STREAM, setIn: BOOL] ~ CODE; SetPort: PUBLIC PROC [port: IO.STREAM, in: BOOL] ~ { SIGNAL SetPortSignal[port, in]; }; DoWithPort: PUBLIC PROC [port: IO.STREAM, proc: PROC, in: BOOL] ~ { proc[ ! GetStdStream => {IF inP = in THEN RESUME[port] ELSE REJECT}; SetPortSignal => {IF setIn = in THEN {port ¬ newPort; RESUME} ELSE REJECT} ]; }; ErrorPrompt: PROC [in, out: IO.STREAM, sig: SIGNAL ANY RETURNS ANY] RETURNS [reject: BOOL ¬ FALSE] ~ { SigToRope: PROC [signal: SIGNAL ANY RETURNS ANY] RETURNS [signalRope: ROPE] ~ { OPEN RuntimeError; signalRope ¬ SELECT signal FROM LOOPHOLE[Aborted] => "Aborted", LOOPHOLE[AbstractionFault] => "AbstractionFault", LOOPHOLE[ArithmeticFault] => "ArithmeticFault", LOOPHOLE[AssignRefCompositeFault] => "AssignRefCompositeFault", LOOPHOLE[BoundsFault] => "BoundsFault", LOOPHOLE[DivideCheck] => "DivideCheck", LOOPHOLE[LinkageFault] => "LinkageFault", LOOPHOLE[NarrowFault] => "NarrowFault", LOOPHOLE[NarrowRefFault] => "NarrowRefFault", LOOPHOLE[NestedProcFault] => "NestedProcFault", LOOPHOLE[NilFault] => "NilFault", LOOPHOLE[ResumeFault] => "ResumeFault", LOOPHOLE[SendMsg] => "SendMsg", LOOPHOLE[StackFault] => "StackFault", LOOPHOLE[StartFault] => "StartFault", LOOPHOLE[UnboundProcedureFault] => "UnboundProcedureFault", LOOPHOLE[Uncaught] => "Uncaught", LOOPHOLE[UnnamedError] => "UnnamedError", LOOPHOLE[UnnamedSignal] => "UnnamedSignal", LOOPHOLE[Unwind] => "Unwind", LOOPHOLE[UnwindFault] => "UnwindFault", LOOPHOLE[ZeroDivisor] => "ZeroDivisor", LOOPHOLE[FileNotFound] => "FileNotFound", ENDCASE => "unrecognized error"; }; IO.PutRope[out, "\n*** Bad News; uncaught ERROR or SIGNAL: "]; IO.PutRope[out, SigToRope[sig]]; IO.PutRope[out, "\n*** REJECT? "]; IO.Flush[out]; SELECT IO.PeekChar[in] FROM Ascii.LF, Ascii.CR => [] ¬ IO.GetChar[in]; ENDCASE; DO c: CHAR ~ IO.GetChar[in]; UNTIL IO.GetChar[in] < ' DO ENDLOOP; SELECT c FROM 'y, 'Y => RETURN [TRUE]; 'n, 'N => RETURN [FALSE]; ENDCASE => IO.PutRope[out, "\n*** Type 'y' to REJECT the signal and land in the system debugger, 'n' to try for the Scheme debugger: "]; ENDLOOP; }; DoWithPorts: PUBLIC PROC [in, out: IO.STREAM, proc: PROC] ~ { proc[ ! GetStdStream => RESUME[IF inP THEN in ELSE out]; SetPortSignal => {IF setIn THEN in ¬ newPort ELSE out ¬ newPort; RESUME}; RuntimeError.UNCAUGHT => IF ErrorPrompt[in, out, signal].reject THEN REJECT ELSE Complain[$ERROR, "Unknown ERROR or SIGNAL"] ]; }; DoWithIOErrorCatch: PUBLIC PROC [proc: PROC] ~ { proc[ ! IO.Error => {Complain[NIL, IO.PutFR1[format: "%g", value: [refAny[NEW[IO.ErrorCode ¬ ec]]]]]}; UXIO.Error => {Complain[NIL, "I/O error"]}; FileNotFound => {Complain[NIL, "File Not Found"]}; IO.Rubout => {Complain[NIL, ""]}; ]; }; OpenFile: PUBLIC PROC [fileName: Rope.ROPE, in: BOOL] RETURNS [IO.STREAM] ~ { RETURN [UXIO.CreateFileStream[name: fileName, access: IF in THEN $read ELSE $write]] }; FileNotFound: ERROR ~ CODE; TryToOpen: PROC [names: LIST OF ROPE, searchRules: LIST OF ROPE] RETURNS [r: OpenedStream] ~ { tried: ProperList ¬ NIL; IF searchRules = NIL THEN searchRules ¬ LIST[NIL]; FOR sR: LIST OF ROPE ¬ searchRules, sR.rest UNTIL sR=NIL DO FOR nms: LIST OF ROPE ¬ names, nms.rest UNTIL nms=NIL DO r.shortFName ¬ nms.first; IF NOT Rope.IsEmpty[nms.first] THEN { r.fullFName ¬ Rope.Concat[sR.first, nms.first]; tried ¬ Cons[r.fullFName, tried]; r.s ¬ UXIO.CreateFileStream[name: r.fullFName, access: read ! UXIO.Error => CONTINUE]; IF r.s # NIL THEN {r.searchRules ¬ sR; RETURN}; }; IF Rope.Size[sR.first] > 0 THEN EXIT; -- don't look for .scheme outside of cwd ENDLOOP; ENDLOOP; DebugPrint[$failedToOpen, Reverse[tried]]; ERROR FileNotFound; }; loadSearchRules: LIST OF ROPE ¬ LIST["", "schemeFiles/", "/usr/local/lib/scheme/"]; FindFileToLoad: PUBLIC PROC [loadeeName: Rope.ROPE, inner: PROC [port: IO.STREAM, doExpand: BOOL]] ~ { fileName: ROPE ~ loadeeName; schemeName: ROPE; xSchemeName: ROPE; SELECT TRUE FROM Rope.Match[pattern: "*.$cheme", object: fileName, case: TRUE] => { xSchemeName ¬ fileName; }; Rope.Match[pattern: "*.*", object: fileName, case: TRUE] => { schemeName ¬ fileName; }; ENDCASE => { schemeName ¬ Rope.Concat[fileName, ".scheme"]; xSchemeName ¬ Rope.Concat[fileName, ".$cheme"]; }; { searchRules: LIST OF ROPE ~ NARROW[ProcessProps.GetProp[$SchemeLoadSearchRules]]; in: OpenedStream ~ TryToOpen[names: LIST[xSchemeName, schemeName], searchRules: IF searchRules # NIL THEN searchRules ELSE loadSearchRules]; Inner: PROC ~ { inner[port: in.s, doExpand: in.shortFName#xSchemeName ! UNWIND => IO.Close[in.s]]; }; ProcessProps.AddPropList[propList: Atom.PutPropOnList[propList: NIL, prop: $SchemeLoadSearchRules, val: in.searchRules], inner: Inner]; IO.Close[in.s]; }; }; GetRope: PUBLIC PROC [self: IO.STREAM, len: INT, demand: BOOL ¬ FALSE] RETURNS [ROPE] ~ { buf: REF TEXT ¬ NEW[TEXT[len]]; [] ¬ IO.GetBlock[self: self, block: buf]; IF demand AND buf.length # len THEN ERROR; RETURN [Rope.FromRefText[buf]] }; debugPrintControl: REF ¬ $TRUE; DebugPrintSwitch: PUBLIC PROC [control: REF] ~ { debugPrintControl ¬ control; }; PrintC: PROC [c: CHAR] ~ TRUSTED MACHINE CODE {"XR_DebugPutChar"}; PrintN: PROC [n: INT] ~ { IF n < 0 THEN PrintC['-]; PrintCard[ABS[n]]; }; PrintCard: PROC [n: CARD] ~ { IF n <= 9 THEN PrintC['0+n] ELSE {PrintCard[n/10]; PrintC['0+(n MOD 10)]} }; PrintOctal: PROC [n: CARD] ~ { IF n = 0 THEN PrintC['0] ELSE { PrintOctal[n/8]; PrintC['0+(n MOD 8)] } }; PrintRopeLiteral: PROC [rope: ROPE] ~ { i: INT ¬ 0; Action: PROC [c: CHAR] RETURNS [quit: BOOL ¬ FALSE] ~ { IF c = '" OR c='\\ THEN PrintC['\\]; PrintC[c]; i ¬ i + 1; RETURN [i > 250] }; PrintC['"]; [] ¬ Rope.Map[base: rope, action: Action]; PrintC['"]; }; PrintRope: PROC [rope: ROPE] ~ { Action: PROC [c: CHAR] RETURNS [quit: BOOL ¬ FALSE] ~ { PrintC[c] }; [] ¬ Rope.Map[base: rope, action: Action]; }; DPrint: PROC [a: Any, terse: BOOL ¬ FALSE] ~ { PrintList: PROC [pair: Pair] ~ { rest: Pair ¬ NIL; rem: INT ¬ width; FOR each: Pair ¬ pair, rest UNTIL each = NIL DO IF rest # NIL THEN PrintC[' ]; IF rem <= 0 THEN {PrintRope["..."]; EXIT}; DPrint[each.car]; rem ¬ rem - 1; WITH each.cdr SELECT FROM p: Pair => rest ¬ p; ENDCASE => { IF each.cdr # NIL THEN { PrintRope[" . "]; DPrint[each.cdr]; }; rest ¬ NIL; }; ENDLOOP; }; IF depth = 0 THEN { PrintRope["#<...>"]; RETURN}; depth ¬ depth - 1; WITH a SELECT FROM pair: Pair => { IF depth = 0 THEN {PrintRope["( . . . )"]; RETURN} ELSE { PrintRope["("]; PrintList[pair]; PrintRope[")"]; }; }; num: Fixnum => PrintN[num­]; num: Flonum => PrintRope["#"]; num: Bignum => PrintRope["#"]; num: Ratnum => PrintRope["#"]; num: Complex => PrintRope["#"]; b: REF BOOL => PrintRope[IF b­ THEN "#t" ELSE "#f"]; v: SimpleVector => { PrintRope["#( . . . )"]; }; symbol: Symbol => { rope: ROPE ~ Atom.GetPName[symbol]; PrintRope[rope]; }; string: String => { PrintRopeLiteral[Scheme.RopeFromString[string]]; }; rope: ROPE => { PrintRope["#"]; }; text: REF TEXT => { PrintRope["#"]; }; char: Char => { PrintRope["#\\"]; PrintC[char­]; }; p: Primitive => { PrintRope["#"]; }; p: SchemePrivate.TidbitProcedure => { PrintRope["#"]; }; s: Syntax => { PrintRope["#"]; }; p: PrimitiveSyntax => { SELECT p­ FROM quote => PrintRope["QUOTE"]; define => PrintRope["DEFINE"]; setBang => PrintRope["SET!"]; lambda => PrintRope["LAMBDA"]; begin => PrintRope["BEGIN"]; if => PrintRope["IF"]; ENDCASE => ERROR; }; env: Environment => { PrintRope["#"]; }; p: Port => { PrintRope["#"]; }; ENDCASE => { IF a = NIL THEN PrintRope["()"] ELSE { PrintRope["#"] } }; depth ¬ depth + 1; }; width: INT ¬ 100; maxDepth: NAT ¬ 40; depth: NAT ¬ 40; DebugPrint: PUBLIC PROC [where: ATOM, any: REF] ~ { depth ¬ 40; PrintC['[]; IF where # NIL THEN PrintRope[Atom.GetPName[where]]; PrintC[' ]; DPrint[any]; PrintC[']]; PrintC['\n]; }; GetEnvFromCommander: PROC [cmd: Commander.Handle] RETURNS [newEnv: Environment] = { Inner: PROC ~ { WITH Atom.GetPropFromList[cmd.propertyList, $SchemeEvironment] SELECT FROM e: Environment => { InitializeEnvironmentStructure[e]; newEnv ¬ e; }; ENDCASE => { e: Environment ~ NewEnvironmentStructure[]; cmd.propertyList ¬ Atom.PutPropOnList[cmd.propertyList, $SchemeEvironment, e]; newEnv ¬ e; }; }; DoWithPorts[in: cmd.in, out: cmd.out, proc: Inner]; }; SchemeCommand: Commander.CommandProc = { userEnv: Environment ~ GetEnvFromCommander[cmd]; ris: IO.STREAM ~ IO.RIS[cmd.commandLine]; promptName: Symbol ~ Atom.MakeAtom["*read-eval-print-prompt*"]; IF Scheme.Read[ris] = endOfFile THEN { DefineVariable[variable: promptName, value: true, env: userEnv]; ReadEvalPrintLoop[cmd.in, cmd.out, userEnv]; } ELSE { DefineVariable[variable: promptName, value: false, env: userEnv]; IO.SetIndex[ris, 0]; ReadEvalPrintLoop[ris, cmd.out, userEnv]; }; }; Commander.Register[key: "Scheme", proc: SchemeCommand, doc: "Scheme read-eval-print loop", interpreted: FALSE ! RuntimeError.UNCAUGHT => { DebugPrint[$SchemeSysImpl, "Failed to register Scheme command"]; CONTINUE } ]; END. h SchemeSysImpl.mesa Copyright Σ 1987, 1988, 1991 by Xerox Corporation. All rights reserved. Michael Plass, December 2, 1991 11:14 am PST Last changed by Pavel on May 16, 1988 7:38:35 pm PDT Carl Hauser, October 17, 1988 2:43:19 pm PDT Call this from pcr to get things started: callall _RunScheme_30 System-dependent functions SetPortSignal is raised by SetPort and caught & resumed by DoWithPort or DoWithPorts We assume that we're in the scope of DoWithPort or DoWithPorts System errors local errors Debug Printing Commander commands [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] Κ0•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ Οeœ=™HK™,K™4K™,K™—KšΟk œžœSžœ˜|K˜KšΠln œžœž˜Kšžœžœ,ž˜KKšžœ˜šœžœžœ˜K˜šžœžœžœ˜K˜—šœžœ˜K˜—šΟn œžœΟcœžœ˜*™)K™—K˜Kšœžœžœžœ˜1Kšœžœžœžœ˜3š œžœ˜šžœž˜ Kšžœ/˜3Kšžœ)˜-—Kšœ ˜ šžœžœž˜Kšœžœžœ žœ ˜*Kšžœ˜—Kšœ˜—Kšœ+˜+Kšœ˜——headš ™šœžœžœžœžœžœ žœžœžœžœžœžœ˜uK˜—š  œžœžœ žœžœžœžœ˜@Kšžœžœ˜Kšœ˜K˜—š œžœžœ žœžœžœžœ˜HK•StartOfExpansion[file: FS.OpenFile]šžœžœ˜ Kšœ˜K˜—š œžœžœ žœžœžœžœ˜NK–[file: FS.OpenFile]šžœžœ˜ Kšœ˜K˜—š  œžœžœ˜"K˜—š  œžœžœžœžœžœžœ˜K–5[key: REF ANY, val: REF ANY, aList: List.AList]šžœ˜Kšœ˜K˜—š  œžœžœžœžœžœžœ˜Cšœ˜Kš œžœ žœžœžœžœ˜Kšžœ˜ Kšžœ ˜"Kšžœ ˜šžœžœž˜Kšœžœžœ žœ ˜*Kšžœ˜—šž˜Kšœžœžœ ˜Kšžœžœžœžœ˜%šžœž˜ Kšœ žœžœ˜Kšœ žœžœ˜Kšžœžœ{˜ˆ—Kšžœ˜—Kšœ˜K˜—š   œžœžœ žœžœžœ˜=šœ˜Kš œžœžœžœžœ˜0Kš œžœžœžœžœ˜IKš œ žœžœ%žœžœžœ,˜|K˜—Kšœ˜K˜—š œžœžœžœ˜0šœ˜Kš žœžœžœ%žœžœ˜^Kšžœžœ˜+Kšœžœ˜2Kšžœžœ ˜&Kšœ˜—Kšœ˜K˜—š œžœžœžœžœžœžœžœ˜MKš žœžœ*žœžœžœ ˜TKšœ˜K˜—Kš  œžœžœ˜K˜š  œžœ žœžœžœžœžœžœžœ˜^Kšœžœ˜Kš žœžœžœžœžœ˜2š žœžœžœžœžœžœž˜;š žœžœžœžœžœžœž˜8K˜šžœžœžœ˜%K˜/K˜!Kšœžœ4žœ žœ˜VKšžœžœžœžœ˜/K˜—Kšžœžœžœ‘(˜NKšžœ˜—Kšžœ˜—Kšœ*˜*Kšžœ˜Kšœ˜K˜—Kš œžœžœžœžœ/˜SK˜š œžœžœžœ žœžœžœ žœ˜fKšœ žœ˜K–6[pattern: ROPE, object: ROPE, case: BOOL _ TRUE]šœ žœ˜K–6[pattern: ROPE, object: ROPE, case: BOOL _ TRUE]šœ žœ˜šžœžœž˜šœ8žœ˜BK˜Kšœ˜—šœ3žœ˜=K˜Kšœ˜—šžœ˜ K˜.K˜/Kšœ˜——˜Kš œ žœžœžœžœ/˜QKš œ$žœ(žœžœžœ žœ˜Œš œžœ˜Kšœ8žœžœ˜RKšœ˜—Kšœ@žœD˜‡Kšžœ ˜K˜—Kšœ˜K˜—š œžœžœžœžœžœ žœžœžœžœ˜YKš œžœžœžœžœ˜K–P[self: STREAM, block: REF TEXT, startIndex: NAT _ 0, count: NAT _ 32767]šœžœ"˜)Kšžœžœžœžœ˜*Kšžœ˜Kšœ˜K˜——š ™Kšœžœ ˜š œžœžœ žœ˜0K˜Kšœ˜K˜—š  œžœžœžœžœΟfœ˜BK˜—š œžœžœ˜Kšžœžœ ˜Kšœ žœ˜Kšœ˜K˜—š  œžœžœ˜Kšžœžœžœ žœ˜IKšœ˜K˜—š  œžœžœ˜Kšžœžœ žœ!žœ˜GKšœ˜K˜—š œžœžœ˜'K–* -- [c: CHAR] RETURNS [quit: BOOL _ FALSE]šœžœ˜ š  œžœžœžœžœžœ˜7Kšžœžœžœ ˜$Kšœ ˜ K˜ Kšžœ ˜K˜—Kšœ ˜ K–T[base: ROPE, start: INT _ 0, len: INT _ 2147483647, action: Rope.ActionType]˜*Kšœ ˜ Kšœ˜K˜—š  œžœžœ˜ Kš  œžœžœžœžœžœ˜DK–T[base: ROPE, start: INT _ 0, len: INT _ 2147483647, action: Rope.ActionType]˜*Kšœ˜K˜—š œžœžœžœ˜.š  œžœ˜ Kšœ žœ˜Kšœžœ ˜šžœžœžœž˜/Kšžœžœžœ ˜Kšžœ žœžœ˜*Kšœ˜K˜šžœ žœž˜K˜šžœ˜ šžœ žœžœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœžœ˜ Kšœ˜——Kšžœ˜—Kšœ˜—Kšžœ žœžœ˜1K˜šžœžœž˜šœ˜šžœ ˜ Kšžœžœ˜%šžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜——K˜—K˜Kšœ&˜&Kšœ&˜&Kšœ&˜&Kšœ(˜(Kš œžœžœžœžœžœ˜4šœ˜Kšœ˜Kšœ˜—šœ˜Kšœžœ˜#Kšœ˜Kšœ˜—šœ˜Kšœ0˜0Kšœ˜—šœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šœžœ˜Kšœ žœ˜Kš žœžœžœžœžœ˜:Kšœ˜Kšœ˜—šœ˜Kšœ˜K˜Kšœ˜—šœ˜Kšœ$˜$Kšœ˜—šœ%˜%Kšœ#˜#Kšœ˜—šœ˜Kšœ˜Kšœ˜—šœ˜šžœž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—Kšœ˜—šœ˜Kšœ˜Kšœ˜—šœ ˜ Kšœ˜Kšœ˜—šžœ˜ šžœž˜ Kšžœ˜Kšžœžœ žœ˜O—Kšœ˜——K˜Kšœ˜K˜—Kšœžœ˜Kšœ žœ˜Kšœžœ˜š   œžœžœ žœžœ˜3K˜ K˜ Kšžœ žœžœ!˜4K˜ Kšœ ˜ K˜ K˜ Kšœ˜——šœ   ™š œžœžœ˜Sš œžœ˜šžœ;žœž˜Jšœ˜Kšœ"˜"K˜ Kšœ˜—šžœ˜ Kšœ+˜+K˜NK˜ Kšœ˜——Kšœ˜—Kšœ3˜3Kšœ˜K˜—š  œ˜(Kš œžœ žœžœžœžœžœ™HKšœ0˜0Kš œžœžœžœžœ˜)Kšœ?˜?šžœ˜šžœ˜K–H[variable: Scheme.Any, value: Scheme.Any, env: Scheme.Environment]šœ@˜@Kšœ,˜,Kšœ˜—šžœ˜K–H[variable: Scheme.Any, value: Scheme.Any, env: Scheme.Environment]šœA˜AKšžœ˜Kšœ)˜)Kšœ˜——K˜K˜—–x[key: ROPE, proc: Commander.CommandProc, doc: ROPE _ NIL, clientData: REF ANY _ NIL, interpreted: BOOL _ TRUE]šœhž˜mšœžœ˜Kšœ@˜@Kšž˜Kšœ˜—Kšœ˜——˜K˜—Kšžœ˜K˜—…—)Ψ@p