DIRECTORY AMBridge USING [FHFromTV, GetWorld, RemoteFHFromTV, TVForReferent, TVForSignal, TVForType, TVToCardinal, TVToLI], AMEvents USING [BootedNotifier, BreakAfter, BreakAt, BreakID, ClearBreak, DuplicateBreakpoint, Event, EventProc, GetEvents, NextBreak, Outcome, RegisterBootedNotifier, StopEvents, UnRegisterBootedNotifier], AMMiniModel USING [GetInterfaceRecord], AMModel USING [Context, ContextName, ContextWorld, MostRecentNamedContext, ParentSection, RootContext, Section, SectionClass, SectionSource, Source], AMModelBridge USING [ContextForFrame], AMModelLocation USING [EntryLocations], AMTypes USING [DynamicParent, Error, GetEmptyTV, TV, TVToName, TVType, Type, TypeClass], AMViewerOps USING [ReportProc, SectionFromSelection, SourceFromTV, ViewerFromSection], Atom USING [GetPropFromList], BackStop USING [Call], CedarProcess USING [DoWithPriority], Commander USING [CommandObject, CommandProc, Handle, Register], EvalQuote USING [EvalQuoteProc, Register], FileViewerOps USING [OpenSource], Interpreter USING [AbortProc, Evaluate], InterpreterOps USING [Eval, GetArg, RegisterTV, Tree, TreeToName, WorldFromHead], InterpreterToolPrivate USING [Break, BreakIndex, BreakObject, Handle, InterpreterObject, nullBreakIndex], IO USING [Close, GetLineRope, Put, PutChar, PutF1, PutFR1, PutRope, Reset, RopeFromROS, ROS, STREAM], List USING [AList, PutAssoc], MBQueue USING [Create, CreateMenuEntry, Queue], Menus USING [ChangeNumberOfLines, InsertMenuEntry, Menu, MenuProc], PrincOps USING [BytePC], PrintTV USING [Print, PrintArguments, PrintSignal, PrintType, PrintVariables], Process USING [Detach, GetCurrent], ProcessProps USING [AddPropList, GetPropList], Rope USING [Cat, Concat, Fetch, IsEmpty, Length, ROPE, Substr], RuntimeError USING [UNCAUGHT], SafeStorage USING [NarrowRefFault], SymTab USING [Create, Fetch, Ref], TiogaOps USING [GetSelection, LastLocWithin, SelectPoint, ViewerDoc], TypeScript USING [Create, Destroy, TS], ViewerClasses USING [Viewer], ViewerEvents USING [EventProc, RegisterEventProc], ViewerIO USING [CreateViewerStreams], ViewerOps USING [AddProp, EstablishViewerPosition, FetchProp, OpenIcon, PaintViewer], UserProfile USING [Boolean, CallWhenProfileChanges, ProfileChangedProc], WorldVM USING [GetWorld, LocalWorld, World, WorldName]; InterpreterToolImpl: CEDAR MONITOR -- protects individual interpreters LOCKS h.LOCK USING h: Handle IMPORTS AMBridge, AMEvents, AMMiniModel, AMModel, AMModelBridge, AMModelLocation, AMTypes, AMViewerOps, Atom, BackStop, CedarProcess, Commander, EvalQuote, FileViewerOps, Interpreter, InterpreterOps, IO, List, MBQueue, Menus, PrintTV, Process, ProcessProps, Rope, RuntimeError, SafeStorage, SymTab, TiogaOps, TypeScript, UserProfile, ViewerEvents, ViewerIO, ViewerOps, WorldVM EXPORTS InterpreterToolPrivate -- nextBI = BEGIN OPEN Interpreter, Rope; TV: TYPE = AMTypes.TV; Type: TYPE = AMTypes.Type; Handle: TYPE = InterpreterToolPrivate.Handle; -- one per viewer InterpreterObject: TYPE = InterpreterToolPrivate.InterpreterObject; BreakIndex: TYPE = InterpreterToolPrivate.BreakIndex; nullBreakIndex: BreakIndex = InterpreterToolPrivate.nullBreakIndex; nextBI: PUBLIC BreakIndex _ 1; -- BEWARE that these guys aren't protected dormantH: Handle _ NIL; BreakObject: TYPE = InterpreterToolPrivate.BreakObject; Break: TYPE = InterpreterToolPrivate.Break; NewInterpreter: Commander.CommandProc = TRUSTED { Process.Detach[LOOPHOLE[FORK CreateTool[NIL--no event--], PROCESS]]; }; CreateTool: PROC [event: AMEvents.Event] RETURNS [outcome: AMEvents.Outcome] = TRUSTED { h: Handle; context: AMModel.Context = IF event = NIL THEN AMModel.RootContext[WorldVM.LocalWorld[]] ELSE AMModelBridge.ContextForFrame[event.frame]; remoteWorld: WorldVM.World _ NIL; inner: PROC = TRUSTED { IF context = NIL THEN ERROR; IF WorldVM.LocalWorld[] # AMModel.ContextWorld[context] THEN remoteWorld _ AMModel.ContextWorld[context]; IF dormantH = NIL THEN { h _ NEW[ InterpreterObject _ [remoteWorld: remoteWorld, context: context, event: event, menuHitQueue: MBQueue.Create[], symTab: SymTab.Create[], readEvalPrintProcess: LOOPHOLE[Process.GetCurrent[]]]]; NewViewer[h]; } ELSE { name: ROPE _ NIL; h _ dormantH; -- NOTE unmonitored dormantH _ NIL; h.remoteWorld _ remoteWorld; h.context _ context; h.event _ event; h.readEvalPrintProcess _ LOOPHOLE[Process.GetCurrent[]]; IF h.event # NIL THEN { IF h.event.world # WorldVM.LocalWorld[] THEN name _ "WORLDSWAP "; name _ Cat[name, "Event: ", EventToName[h.event]]; } ELSE name _ Rope.Concat["Interp: ", AMModel.ContextName[h.context]]; h.ts.name _ name; IF h.ts.iconic THEN ViewerOps.OpenIcon[h.ts]; IF h.event # NIL THEN ChangeLines[h.ts, 2] ELSE ChangeLines[h.ts, 1]; h.tsOutStream.PutRope[Rope.Concat[name, "\n"]]; }; IF remoteWorld # NIL THEN AMEvents.RegisterBootedNotifier[BootReturnRequested, remoteWorld, h]; outcome _ MainLoop[h]; IF remoteWorld # NIL THEN AMEvents.UnRegisterBootedNotifier[BootReturnRequested, remoteWorld, h]; }; CedarProcess.DoWithPriority[normal, inner]; }; EventHandler: AMEvents.EventProc = TRUSTED { h: Handle _ NIL; nestingLevel: NAT; -- that of saved interp status context: AMModel.Context = AMModelBridge.ContextForFrame[event.frame]; [h, nestingLevel] _ FindInProgressEvaluation[]; IF h # NIL AND h.nestingLevel = nestingLevel THEN { -- if this event is "under" an interpreter oldRemoteWorld: WorldVM.World = h.remoteWorld; -- save remoteWorld; oldContext: AMModel.Context = h.context; -- save context; oldGlobalContext: AMModel.Context = h.globalContext; -- save globalContext; oldEvent: AMEvents.Event = h.event; -- save event; oldName: ROPE = h.ts.name; -- save viewer name; newName: ROPE _ NIL; IF event.world # WorldVM.LocalWorld[] THEN newName _ "WORLDSWAP "; newName _ Cat[newName, "Event: ", EventToName[event]]; IO.PutF1[h.tsOutStream, "***Nesting this InterpreterTool to be a handler for %g\n", [rope[newName]] ]; IF oldEvent = NIL THEN ChangeLines[h.ts, 2]; IF oldRemoteWorld = NIL THEN h.remoteWorld _ IF WorldVM.LocalWorld[] = AMModel.ContextWorld[context] THEN NIL ELSE AMModel.ContextWorld[context] ELSE { IF WorldVM.LocalWorld[] # AMModel.ContextWorld[context] AND oldRemoteWorld # AMModel.ContextWorld[context] THEN ERROR; }; h.context _ context; h.globalContext _ NIL; h.event _ event; h.ts.name _ newName; ViewerOps.PaintViewer[h.ts, caption]; h.nestingLevel _ h.nestingLevel + 1; IF oldRemoteWorld = NIL AND h.remoteWorld # NIL THEN AMEvents.RegisterBootedNotifier[BootReturnRequested, h.remoteWorld, h]; outcome _ MainLoop[h]; IF oldRemoteWorld = NIL AND h.remoteWorld # NIL THEN AMEvents.UnRegisterBootedNotifier [BootReturnRequested, h.remoteWorld, h]; h.ts.name _ oldName; h.nestingLevel _ h.nestingLevel - 1; h.event _ oldEvent; h.globalContext _ oldGlobalContext; h.context _ oldContext; h.remoteWorld _ oldRemoteWorld; ViewerOps.PaintViewer[h.ts, caption]; IF oldEvent = NIL THEN ChangeLines[h.ts, 1]; } ELSE outcome _ CreateTool[event]; -- if this event is not "under" an interpreter }; NewViewer: PROC [h: Handle] = { name: ROPE _ NIL; LocalRegister: PROC [name: ROPE, ref: REF, help: ROPE] = TRUSTED { ENABLE AMTypes.Error => GO TO err; InterpreterOps.RegisterTV[ name: name, tv: AMBridge.TVForReferent[ref], help: help, symTab: h.symTab ]; EXITS err => { IO.PutF1[h.tsOutStream, "** Failed to register %g\n", [rope[name]]]; }; }; TRUSTED { IF h.event # NIL THEN { IF h.event.world # WorldVM.LocalWorld[] THEN name _ "WORLDSWAP "; name _ Cat[name, "Event: ", EventToName[h.event]]; } ELSE name _ Rope.Concat["Interp: ", AMModel.ContextName[h.context]]; }; h.ts _ TypeScript.Create[info: [name: name, column: right, iconic: FALSE]]; CreateInterpreterMenu[h]; ViewerOps.AddProp[h.ts, $InterpreterHandle, h]; [h.tsInStream, h.tsOutStream] _ ViewerIO.CreateViewerStreams[name: NIL, viewer: h.ts]; h.tsOutStream.PutRope[Rope.Concat[name, "\n"]]; LocalRegister[ "&H", NEW[Handle _ h], "this interpretertool's handle"]; LocalRegister[ "&depth", NEW[INT _ 4], "printing depth for this interpretertool"]; LocalRegister[ "&width", NEW[INT _ 32], "printing width for this interpretertool"]; LocalRegister[ "&WalkStack", NEW[PROC [nFrames: INT _ 1, h: Handle _ NIL] _ WalkStack], "set a local frame context (eventhandler)"]; LocalRegister[ "&slf", NEW[PROC [nFrames: INT _ 1, h: Handle _ NIL] _ WalkStack], "set a local frame context (eventhandler)"]; LocalRegister[ "&Proceed", NEW[PROC [h: Handle _ NIL] _ SetProceedRequested], "proceed the current event"]; LocalRegister[ "&Abort", NEW[PROC [h: Handle _ NIL] _ SetStopRequested], "abort the current event"]; LocalRegister[ "&ShowFrame", NEW[PROC [h: Handle _ NIL] _ ShowFrame], "show the current lf context (eventhandler)"]; LocalRegister[ "&Source", NEW[PROC [h: Handle _ NIL] _ Source], "show source loc of current lf context (eventhandler)"]; LocalRegister[ "&SetBreak", NEW[PROC [h: Handle _ NIL, exit: BOOL _ FALSE] _ SetBreak], "set break at selected source loc (eventhandler)"]; LocalRegister[ "&ClearBreak", NEW[PROC [h: Handle _ NIL, breakIndex: BreakIndex _ nullBreakIndex] _ ClearBreak], "clear specified break"]; LocalRegister[ "&ClearAllBreaks", NEW[PROC [h: Handle _ NIL] _ ClearAllBreaks], "clear all breaks"]; LocalRegister[ "&ListBreaks", NEW[PROC [h: Handle _ NIL] _ ListBreaks], "list all breaks"]; EvalQuote.Register["&sgf", SetGlobalFrameHelper, h.symTab, h]; LocalRegister[ "&sgf", NEW[PROC [progName: ROPE, h: Handle _ NIL] _ SetGlobalFrameContext], "&sgf[rope]\tset context to be that for the given module"]; EvalQuote.Register["&gf", GlobalFrameHelper, h.symTab, h]; LocalRegister[ "&gf", NEW[PROC [progName: ROPE, h: Handle _ NIL] RETURNS [TV] _ GlobalFrameContext], "&gf[rope]\tget the given module's context"]; EvalQuote.Register["&sw", SetWorldHelper, h.symTab, h]; LocalRegister[ "&sw", NEW[PROC [worldName: ROPE, h: Handle _ NIL] _ SetWorldContext], "&sw[rope]\tset context to be that for the given world"]; EvalQuote.Register["&sir", SetIRHelper, h.symTab, h]; LocalRegister[ "&sir", NEW[PROC [interfaceName: ROPE, h: Handle _ NIL] _ SetIRContext], "&sir[rope]\tset context to be that for the given IR"]; EvalQuote.Register["&type", TypeHelper, h.symTab, h]; LocalRegister[ "&type", NEW[PROC [expr: ROPE, h: Handle _ NIL] RETURNS [Type] _ TypeGetter], "&type[expr]\tget the type of the given expr"]; EvalQuote.Register["&ir", IRHelper, h.symTab, h]; LocalRegister[ "&ir", NEW[PROC [interfaceName: ROPE, h: Handle _ NIL] RETURNS [TV] _ IRContext], "&ir[rope]\tget the given IR"]; }; EventToName: PROC [event: AMEvents.Event] RETURNS [name: ROPE _ NIL] = TRUSTED { reason: ROPE; s: IO.STREAM _ NIL; WITH e: event SELECT FROM break => { break: Break _ NIL; IF e.clientData # NIL THEN break _ NARROW[e.clientData, Break ! SafeStorage.NarrowRefFault => CONTINUE]; IF break = NIL THEN reason _ "Unknown breakpoint hit." ELSE reason _ IO.PutFR1["Breakpoint #%g hit.", [integer[break.index]]]; }; call => reason _ Rope.Concat["Call: ", e.msg]; signal => { inner: SAFE PROC = TRUSTED { PrintTV.PrintSignal[e.signal, e.args, s]; IF AMTypes.TypeClass[AMTypes.TVType[e.signal]] = cardinal THEN [] _ AMBridge.TVForSignal[LOOPHOLE[AMBridge.TVToCardinal[e.signal], ERROR ANY RETURNS ANY]]; }; s _ IO.ROS[]; s.PutRope[BackStop.Call[inner]]; reason _ IO.RopeFromROS[s]; }; unknown => reason _ Rope.Concat["Unknown: ", e.why]; ENDCASE => ERROR; name _ Cat[reason, ", world: ", WorldVM.WorldName[event.world]]; { inner: SAFE PROC = TRUSTED { s.PutRope[", context: "]; s.PutRope[AMModel.ContextName[event.frame]]; s.PutRope[", process: "]; PrintTV.Print[event.process, s, 2, 16]; }; s _ IO.ROS[]; s.PutRope[BackStop.Call[inner]]; name _ Rope.Concat[name, IO.RopeFromROS[s]]; IF Rope.Length[name] > 1000 THEN { name _ Rope.Concat[Rope.Substr[name, 0, 1000], "..."]; }; }; }; CreateInterpreterMenu: PROC [h: Handle] = { menu: Menus.Menu _ h.ts.menu; InsME: PROC [line: NAT, name: ROPE, proc: Menus.MenuProc] = { Menus.InsertMenuEntry [menu: menu, line: line, entry: MBQueue.CreateMenuEntry [q: h.menuHitQueue, name: name, proc: proc, clientData: h]]; }; InsME[line: 0, name: "STOP!", proc: StopHit]; InsME[line: 0, name: "SetBreak", proc: SetBreakHit]; InsME[line: 0, name: "ClearBreak(s)", proc: ClearBreakHit]; InsME[line: 0, name: "ListBreaks", proc: ListBreaksHit]; InsME[line: 1, name: "WalkStack", proc: WalkStackHit]; InsME[line: 1, name: "ShowFrame", proc: ShowFrameHit]; InsME[line: 1, name: "Proceed", proc: ProceedHit]; InsME[line: 1, name: "Abort", proc: AbortHit]; InsME[line: 1, name: "Source", proc: SourceHit]; IF h.event # NIL THEN ChangeLines[h.ts, 2] ELSE ViewerOps.PaintViewer[h.ts, menu]; }; ChangeLines: PROC [v: ViewerClasses.Viewer, nLines: NAT] = { Menus.ChangeNumberOfLines[v.menu, nLines]; ViewerOps.EstablishViewerPosition[v, v.wx, v.wy, v.ww, v.wh]; ViewerOps.PaintViewer[v, all]; }; GetIntFromTable: PROC [h: Handle, name: ROPE, default: INT] RETURNS [INT] = TRUSTED { WITH SymTab.Fetch[h.symTab, name].val SELECT FROM tv: TV => RETURN [AMBridge.TVToLI[tv ! AMTypes.Error => CONTINUE]]; ENDCASE; RETURN [default]; }; MainLoop: PROC [h: Handle] RETURNS [outcome: AMEvents.Outcome _ [proceed[NIL]]] = { ENABLE UNWIND => h.event _ NIL; somethingHappened: BOOL _ TRUE; out: IO.STREAM _ h.tsOutStream; out.PutChar['\n]; UNTIL WasTerminateRequested[h] DO line: ROPE _ NIL; result: TV _ NIL; noResult: BOOL _ TRUE; errorRope: ROPE _ NIL; prompt: ROPE _ IO.PutFR1["&%g _ ", [integer[NextVarIndex[h, somethingHappened]]]]; leader: ROPE _ NIL; printType: BOOL _ FALSE; depth: INT _ GetIntFromTable[h, "&depth", 4]; width: INT _ GetIntFromTable[h, "&width", 32]; innerPrint: SAFE PROC = TRUSTED { IF noResult THEN RETURN; IO.PutRope[out, "=> "]; IF printType THEN { IO.PutRope[out, "(type) "]; PrintTV.PrintType[ put: out, type: AMTypes.TVType[result], depth: depth, width: width, verbose: depth > 4 ]; } ELSE PrintTV.Print[ put: out, tv: result, depth: depth, width: width, verbose: depth > 4 ]; }; brq: BOOL; brqWorld: WorldVM.World _ NIL; somethingHappened _ FALSE; IF WasProceedRequested[h] THEN { ResetProceedRequested[h]; IF h.event # NIL THEN { IF h.nestingLevel = 0 THEN {SetDormant[h]; h.event _ NIL}; RETURN; }; }; IF WasAbortRequested[h] THEN { ResetAbortRequested[h]; IF h.nestingLevel > 0 THEN RETURN[[quit[]]] -- RETURN => event proc returns ELSE IF h.event # NIL THEN {SetDormant[h]; h.event _ NIL; RETURN[[quit[]]]}; }; [brq, brqWorld] _ WasBootReturnRequested[h]; IF brq THEN { IF brqWorld = h.remoteWorld THEN { IF h.nestingLevel = 0 THEN {ResetBootReturnRequested[h]; SetDormant[h]; h.event _ NIL}; RETURN[[quit[]]]; } ELSE ResetBootReturnRequested[h]; }; FOR i: NAT IN [0..h.nestingLevel) DO leader _ Rope.Concat[leader, "<***>"]; ENDLOOP; out.PutRope[leader ! RuntimeError.UNCAUGHT => CONTINUE]; out.PutRope[prompt ! RuntimeError.UNCAUGHT => CONTINUE]; { line _ h.tsInStream.GetLineRope[ ! RuntimeError.UNCAUGHT => GOTO handleAborted; ]; EXITS handleAborted => { ENABLE RuntimeError.UNCAUGHT => CONTINUE; h.tsInStream.Reset[]; out.PutRope[" XXX\n"]; }; }; SetStuffable[h]; IF line.IsEmpty[] THEN LOOP; UNTIL line.IsEmpty[] DO ch: CHAR _ line.Fetch[line.Length[] - 1]; SELECT ch FROM '! => {depth _ depth + 1; width _ width + width}; '? => printType _ TRUE; ENDCASE => EXIT; line _ Rope.Substr[base: line, len: line.Length[] - 1]; ENDLOOP; line _ Rope.Concat[line, "\n"]; somethingHappened _ TRUE; ResetStopRequested[h]; { innerEval: SAFE PROC = TRUSTED { [result, errorRope, noResult] _ Interpreter.Evaluate [rope: Rope.Concat[prompt, line], context: IF h.globalContext # NIL THEN h.globalContext ELSE h.context, symTab: h.symTab, abort: [abortProc, h] ! ABORTED, UNWIND => {errorRope _ " XXX\n"; CONTINUE}; ]; }; ch: Commander.Handle = NEW [Commander.CommandObject _ [ in: h.tsInStream, out: out, err: out, commandLine: line, command: "_", propertyList: NIL]]; props: List.AList _ NIL; props _ List.PutAssoc[$CommanderHandle, ch, props]; props _ List.PutAssoc[$InterpreterHandle, h, props]; props _ List.PutAssoc[$InterpreterNestingLevel, NEW[NAT _ h.nestingLevel], props]; props _ List.PutAssoc[$InterpreterSymTab, h.symTab, props]; ProcessProps.AddPropList[props, innerEval]; }; IF errorRope.Length[] # 0 THEN IO.PutF1[out, "*** %g\n", [rope[errorRope]] ] ELSE IO.PutF1[out, " %g\n", [rope[BackStop.Call[innerPrint]]] ]; ENDLOOP; IF h.nestingLevel > 0 THEN RETURN[[quit[]]] ELSE Finalize[h]; }; abortProc: Interpreter.AbortProc = TRUSTED { RETURN[WasStopRequested[NARROW[data, Handle]]]; }; FindInProgressEvaluation: PROC RETURNS [h: Handle _ NIL, nestingLevel: NAT _ 0] = { hn: Handle = NARROW[Atom.GetPropFromList[ProcessProps.GetPropList[], $InterpreterHandle]]; rn: REF NAT = NARROW[Atom.GetPropFromList[ProcessProps.GetPropList[], $InterpreterNestingLevel]]; IF hn # NIL AND rn # NIL THEN RETURN[hn, rn^]; }; GetHandlePlease: PUBLIC PROC RETURNS [Handle] = { r: REF = Atom.GetPropFromList[ProcessProps.GetPropList[], $InterpreterHandle]; RETURN[NARROW[r, Handle]]; }; Finalize: PROC [h: Handle] = { out: IO.STREAM _ h.tsOutStream; ts: TypeScript.TS _ h.ts; h.context _ NIL; h.globalContext _ NIL; h.event _ NIL; h.symTab _ NIL; h.ts _ NIL; h.tsInStream _ NIL; h.tsOutStream _ NIL; h.menuHitQueue _ NIL; IF h = dormantH THEN dormantH _ NIL; { ENABLE RuntimeError.UNCAUGHT => CONTINUE; IF out # NIL THEN IO.PutRope[out, "\n\n ~~~~~~~~~~~~~TERMINATED~~~~~~~~~~~~~ \n\n"]; IF ts # NIL THEN TypeScript.Destroy[ts]; IF out # NIL THEN IO.Close[out]; }; }; NextVarIndex: ENTRY PROC [h: Handle, somethingHappened: BOOL] RETURNS [INT] = { ENABLE UNWIND => NULL; IF NOT somethingHappened THEN RETURN[h.nextVarIndex]; RETURN[h.nextVarIndex _ h.nextVarIndex + 1]; }; ResetStopRequested: ENTRY PROC [h: Handle] = { ENABLE UNWIND => NULL; h.stopRequested _ FALSE; }; SetStopRequested: PROC [h: Handle] = { ENABLE UNWIND => NULL; h.stopRequested _ TRUE; StuffIt[h, "\n"]; }; WasStopRequested: ENTRY PROC [h: Handle] RETURNS [BOOL] = { ENABLE UNWIND => NULL; RETURN[h.stopRequested]; }; StuffIt: ENTRY PROC [h: Handle, rope: ROPE] = { ENABLE UNWIND => NULL; UNTIL h.stuffAble DO WAIT h.Stuffable; ENDLOOP; h.stuffAble _ FALSE; h.tsInStream.Reset[]; IF IsEmpty[rope] THEN RETURN; IF TiogaOps.GetSelection[].viewer = h.ts THEN TiogaOps.SelectPoint[viewer: h.ts, caret: TiogaOps.LastLocWithin[TiogaOps.ViewerDoc[h.ts]]]; h.ts.class.notify[h.ts, LIST[rope]]; }; SetStuffable: ENTRY PROC [h: Handle] = { ENABLE UNWIND => NULL; h.stuffAble _ TRUE; NOTIFY h.Stuffable; }; SetDormant: ENTRY PROC [h: Handle] = { ENABLE UNWIND => NULL; abort: BOOL _ FALSE; h.readEvalPrintProcess _ NIL; h.tsOutStream.PutRope["\n~~~~~~~~~~~~~~~~~~~~~\n" ! RuntimeError.UNCAUGHT => CONTINUE]; ChangeLines[h.ts, 0 ! RuntimeError.UNCAUGHT => {abort _ TRUE; CONTINUE}]; IF NOT abort THEN dormantH _ h; }; SetProceedRequested: ENTRY PROC [h: Handle] = { ENABLE UNWIND => NULL; h.proceedRequested _ TRUE; }; ResetProceedRequested: ENTRY PROC [h: Handle] = { ENABLE UNWIND => NULL; h.proceedRequested _ FALSE; }; WasProceedRequested: ENTRY PROC [h: Handle] RETURNS [BOOL] = { ENABLE UNWIND => NULL; RETURN[h.proceedRequested]; }; SetBootReturnRequested: ENTRY PROC [h: Handle, world: WorldVM.World] = { ENABLE UNWIND => NULL; h.bootReturnRequested _ TRUE; h.bootedWorld _ world; }; ResetBootReturnRequested: ENTRY PROC [h: Handle] = { ENABLE UNWIND => NULL; h.bootReturnRequested _ FALSE; }; WasBootReturnRequested: ENTRY PROC [h: Handle] RETURNS [yes: BOOL, world: WorldVM.World] = { ENABLE UNWIND => NULL; RETURN[h.bootReturnRequested, h.bootedWorld]; }; SetAbortRequested: ENTRY PROC [h: Handle] = { ENABLE UNWIND => NULL; h.abortRequested _ TRUE; }; ResetAbortRequested: ENTRY PROC [h: Handle] = { ENABLE UNWIND => NULL; h.abortRequested _ FALSE; }; WasAbortRequested: ENTRY PROC [h: Handle] RETURNS [BOOL] = { ENABLE UNWIND => NULL; RETURN[h.abortRequested]; }; SetTerminateRequested: ENTRY PROC [h: Handle] = { ENABLE UNWIND => NULL; IF h.tsInStream # NIL THEN h.tsInStream.Close[ ! RuntimeError.UNCAUGHT => CONTINUE]; IF h = dormantH THEN dormantH _ NIL; h.terminateRequested _ TRUE; }; WasTerminateRequested: ENTRY PROC [h: Handle] RETURNS [BOOL] = { ENABLE UNWIND => NULL; RETURN[h.terminateRequested]; }; StopHit: Menus.MenuProc = TRUSTED { SetStopRequested[NARROW[clientData, Handle]]; }; HighlightBreakPoint: PROC [break: Break, err: IO.STREAM] = { report: AMViewerOps.ReportProc = TRUSTED {err.PutRope[msg]}; inner: SAFE PROC = TRUSTED { [] _ AMViewerOps.ViewerFromSection[break.section, report]; }; -- yekk. msg: ROPE _ BackStop.Call[inner]; IF msg # NIL THEN err.PutRope[msg]; }; SetBreakHit: Menus.MenuProc = TRUSTED { h: Handle = NARROW[clientData, Handle]; SELECT mouseButton FROM blue => StuffIt[h, " ---- &SetBreak[h: &H, exit: TRUE]\n"]; ENDCASE => StuffIt[h, " ---- &SetBreak[h: &H]\n"]; }; SetBreak: PROC [h: Handle _ NIL, exit: BOOL _ FALSE] = TRUSTED { break: Break _ NIL; msg: ROPE _ NIL; err: ROPE _ NIL; world: WorldVM.World; inner: SAFE PROC = TRUSTED { section: AMModel.Section _ NIL; warning: REF; h.tsOutStream.PutRope["Setting break..."]; [section, warning] _ AMViewerOps.SectionFromSelection[world]; IF warning = NIL THEN h.tsOutStream.PutRope["-- possible source version mismatch --"]; SELECT AMModel.SectionClass[section] FROM proc => {}; statement => { IF exit THEN section _ AMModel.ParentSection[section]; }; ENDCASE => { err _ "-- section is not valid --"; RETURN; }; break _ NEW[BreakObject _ [index: 0, breakID: NIL, world: world, section: section]]; {ENABLE AMEvents.DuplicateBreakpoint => GO TO bogus; break.breakID _ IF exit THEN AMEvents.BreakAfter[world, section, break] ELSE AMEvents.BreakAt[world, section, break]; break.index _ nextBI; nextBI _ nextBI + 1; EXITS bogus => { break _ NIL; err _ "-- duplicate breakpoints not allowed --"; }; }; }; IF h = NIL THEN h _ GetHandlePlease[]; world _ IF h.event # NIL THEN h.event.world ELSE AMModel.ContextWorld[h.context]; msg _ BackStop.Call[inner]; IF msg # NIL THEN err _ msg; IF err.Length[] = 0 AND break # NIL THEN { h.tsOutStream.PutF1["Break #%g set.", [integer[break.index]]]; HighlightBreakPoint[break: break, err: h.tsOutStream]; RETURN; }; h.tsOutStream.PutRope[err]; }; ListBreaksHit: Menus.MenuProc = TRUSTED { h: Handle = NARROW[clientData, Handle]; StuffIt[h, " ---- &ListBreaks[h: &H]\n"]; }; SetGlobalFrameContext: PROC [progName: ROPE, h: Handle _ NIL] = TRUSTED { ERROR -- defined only for &help; the evalquote proc does the work }; GlobalFrameContext: PROC [progName: ROPE, h: Handle _ NIL] RETURNS [TV] = TRUSTED { ERROR -- defined only for &help; the evalquote proc does the work }; SetWorldContext: PROC [worldName: ROPE, h: Handle _ NIL] = TRUSTED { ERROR -- defined only for &help; the evalquote proc does the work }; SetIRContext: PROC [interfaceName: ROPE, h: Handle _ NIL] = TRUSTED { ERROR -- defined only for &help; the evalquote proc does the work }; IRContext: PROC [interfaceName: ROPE, h: Handle _ NIL] RETURNS [TV] = TRUSTED { ERROR -- defined only for &help; the evalquote proc does the work }; TypeGetter: PROC [expr: ROPE, h: Handle _ NIL] RETURNS [Type] = TRUSTED { ERROR -- defined only for &help; the evalquote proc does the work }; ListBreaks: PROC [h: Handle _ NIL] = TRUSTED { msg: ROPE _ NIL; out: IO.STREAM _ NIL; inner: SAFE PROC = TRUSTED { id: AMEvents.BreakID _ NIL; clientData: REF; DO world: WorldVM.World = IF h.event # NIL THEN h.event.world ELSE AMModel.ContextWorld[h.context]; [id, clientData] _ AMEvents.NextBreak[world: world, prev: id]; IF id = NIL THEN EXIT; WITH clientData SELECT FROM b: Break => { source: AMModel.Source = AMModel.SectionSource[b.section]; pc: PrincOps.BytePC = AMModelLocation.EntryLocations[b.section].list.first.pc; firstCharIndex: INT _ 0; WITH s: source SELECT FROM field => firstCharIndex _ s.firstCharIndex; ENDCASE; IF b.world # world THEN {out.PutRope["DISASTER"]; ERROR}; out.PutF1[" Break #%g at ", [integer[b.index]]]; out.Put[[rope[source.fileName]], [rope["["]], [integer[firstCharIndex]]]; out.PutF1["], bytePC = %bb\n", [cardinal[pc]]]; }; ENDCASE; ENDLOOP; }; IF h = NIL THEN h _ GetHandlePlease[]; out _ h.tsOutStream; out.PutRope["Listing all breaks for this world...\n"]; msg _ BackStop.Call[inner]; IF msg # NIL THEN out.PutF1["Error: %g\n", [rope[msg]]] ELSE out.PutRope["...Done.\n"]; }; ClearBreakHit: Menus.MenuProc = TRUSTED { h: Handle = NARROW[clientData, Handle]; SELECT mouseButton FROM red => StuffIt[h, " ---- &ClearBreak[h: &H]\n"]; blue => StuffIt[h, " ---- &ClearAllBreaks[h: &H]\n"]; ENDCASE; }; ClearAllBreaks: PROC [h: Handle _ NIL] = TRUSTED { msg: ROPE _ NIL; out: IO.STREAM _ NIL; inner: SAFE PROC = TRUSTED { id: AMEvents.BreakID _ NIL; clientData: REF; DO world: WorldVM.World = IF h.event # NIL THEN h.event.world ELSE AMModel.ContextWorld[h.context]; [id, clientData] _ AMEvents.NextBreak[world: world, prev: id]; IF id = NIL THEN EXIT; WITH clientData SELECT FROM b: Break => { IF b.world # world THEN {h.tsOutStream.PutRope["DISASTER"]; ERROR}; AMEvents.ClearBreak[b.breakID]; out.Put[[rope[" Break #"]], [integer[b.index]], [rope[" cleared.\n"]] ]; }; ENDCASE; ENDLOOP; }; IF h = NIL THEN h _ GetHandlePlease[]; out _ h.tsOutStream; out.PutRope["Clearing all breaks...\n"]; msg _ BackStop.Call[inner]; IF msg # NIL THEN out.PutF1["Error: %g\n", [rope[msg]]] ELSE out.PutRope["...Done.\n"]; }; ClearBreak: PROC [h: Handle _ NIL, breakIndex: BreakIndex _ nullBreakIndex] = TRUSTED { msg, err: ROPE _ NIL; break: Break _ NIL; out: IO.STREAM _ NIL; inner: SAFE PROC = TRUSTED { IF breakIndex = nullBreakIndex THEN { IF h.event = NIL THEN err _ "not an event handler" ELSE WITH e: h.event SELECT FROM break => { AMEvents.ClearBreak[e.id]; WITH e.clientData SELECT FROM br: Break => break _ br; ENDCASE; IF break = NIL THEN err _ "I didn't place this break but I cleared it anyhow" ELSE breakIndex _ break.index; }; ENDCASE => err _ "not a break event"; } ELSE { id: AMEvents.BreakID _ NIL; clientData: REF; DO world: WorldVM.World = IF h.event # NIL THEN h.event.world ELSE AMModel.ContextWorld[h.context]; [id, clientData] _ AMEvents.NextBreak[world: world, prev: id]; IF id = NIL THEN {err _ "No break found with the specified index"; EXIT}; WITH clientData SELECT FROM b: Break => { IF b.world # world THEN {h.tsOutStream.PutRope["DISASTER"]; ERROR}; IF b.index = breakIndex THEN { break _ b; AMEvents.ClearBreak[b.breakID]; }; }; ENDCASE; ENDLOOP; }; }; IF h = NIL THEN h _ GetHandlePlease[]; out _ h.tsOutStream; IO.PutRope[out, "Clearing break..."]; msg _ BackStop.Call[inner]; SELECT TRUE FROM msg # NIL => IO.PutF1[out, "Break not cleared: %g", [rope[msg]] ]; break = NIL => IO.PutRope[out, err]; ENDCASE => IO.PutF1[out, "Break #%g cleared.", [integer[breakIndex]] ]; }; WalkStackHit: Menus.MenuProc = TRUSTED { h: Handle = NARROW[clientData, Handle]; SELECT mouseButton FROM red => StuffIt[h, " ---- &WalkStack[nFrames: 1, h: &H]\n"]; yellow => StuffIt[h, " ---- &WalkStack[nFrames: -1000, h: &H]\n"]; blue => StuffIt[h, " ---- &WalkStack[nFrames: -1, h: &H]\n"]; ENDCASE => ERROR; }; WalkStack: PROC [nFrames: INT _ 1, h: Handle _ NIL] = { inner: SAFE PROC = TRUSTED { IF h.event = NIL OR h.event.frame = NIL THEN RETURN; WalkContext[h, nFrames]; PrintTV.Print[tv: h.context, put: h.tsOutStream, depth: 1, verbose: TRUE]; }; IF h = NIL THEN h _ GetHandlePlease[]; h.tsOutStream.PutRope[BackStop.Call[inner]]; }; WalkContext: ENTRY PROC [h: Handle, n: INT] = TRUSTED { ENABLE UNWIND => NULL; h.globalContext _ NIL; SELECT n FROM > 0 => { next: TV _ NIL; this: TV _ h.context; THROUGH [1..n] DO this _ AMTypes.DynamicParent[this]; IF this = NIL THEN {h.tsOutStream.PutRope["Can't go any further..."]; EXIT}; next _ this; ENDLOOP; IF next # NIL THEN h.context _ AMModelBridge.ContextForFrame[next]; }; < -999 => h.context _ AMModelBridge.ContextForFrame[h.event.frame]; < 0 => { this: TV _ h.context; prev: TV _ h.event.frame; THROUGH [1..-n] DO t: TV; IF FHBits[prev] = FHBits[this] THEN { h.tsOutStream.PutRope["Can't go any further."]; h.context _ AMModelBridge.ContextForFrame[prev]; RETURN}; t _ AMTypes.DynamicParent[prev]; UNTIL FHBits[t] = FHBits[this] DO prev _ t; t _ AMTypes.DynamicParent[prev] ENDLOOP; this _ prev; ENDLOOP; h.context _ AMModelBridge.ContextForFrame[prev]; }; ENDCASE; }; FHBits: PROC [lf: TV] RETURNS [fhBits: CARDINAL] = TRUSTED { local: BOOL = AMBridge.GetWorld[lf] = WorldVM.LocalWorld[]; fhBits _ IF local THEN LOOPHOLE[AMBridge.FHFromTV[lf], CARDINAL] ELSE LOOPHOLE[AMBridge.RemoteFHFromTV[lf].fh, CARDINAL]; }; ShowFrameHit: Menus.MenuProc = TRUSTED { h: Handle = NARROW[clientData, Handle]; StuffIt[h, " ---- &ShowFrame[h: &H]\n"]; }; ProceedHit: Menus.MenuProc = TRUSTED { h: Handle = NARROW[clientData, Handle]; SetProceedRequested[h]; StuffIt[h, "\n"]; }; AbortHit: Menus.MenuProc = TRUSTED { h: Handle = NARROW[clientData, Handle]; SetAbortRequested[h]; StuffIt[h, "\n"]; }; BootReturnRequested: AMEvents.BootedNotifier = TRUSTED { h: Handle = NARROW[clientData, Handle]; SetBootReturnRequested[h, world]; StuffIt[h, "\n"]; }; SourceHit: Menus.MenuProc = TRUSTED { h: Handle = NARROW[clientData, Handle]; StuffIt[h, " ---- &Source[h: &H]\n"]; }; Source: PROC [h: Handle _ NIL] = { name: ROPE; index: INT; report: AMViewerOps.ReportProc = TRUSTED { h.tsOutStream.PutRope[msg]}; IF h = NIL THEN h _ GetHandlePlease[]; [name, index] _ AMViewerOps.SourceFromTV[h.context, report]; IF name # NIL THEN FileViewerOps.OpenSource[fileName: name, index: index, feedBack: h.tsOutStream]; }; ViewerEvent: ViewerEvents.EventProc = { SELECT event FROM destroy => WITH ViewerOps.FetchProp[viewer, $InterpreterHandle] SELECT FROM h: Handle => { IF h.event # NIL THEN RETURN [TRUE]; IF NOT h.terminateRequested THEN TRUSTED { SetTerminateRequested[h]; Process.Detach[FORK StuffIt[h, "\n"]]; }; IF h = dormantH THEN dormantH _ NIL; }; ENDCASE; ENDCASE; }; ShowFrame: PROC [h: Handle _ NIL] = { lf: TV; depth: INT _ 4; width: INT _ 32; IF h = NIL THEN h _ GetHandlePlease[]; IF h.event = NIL OR h.event.frame = NIL OR h.globalContext # NIL THEN RETURN; depth _ GetIntFromTable[h, "&depth", depth]; width _ GetIntFromTable[h, "&width", width]; lf _ h.context; PrintTV.Print[tv: lf, put: h.tsOutStream, depth: 1, verbose: TRUE]; h.tsOutStream.PutRope["\nArguments--\n"]; PrintTV.PrintArguments[tv: lf, put: h.tsOutStream, depth: depth, width: width, breakBetweenItems: TRUE]; h.tsOutStream.PutRope["\nVariables--\n"]; PrintTV.PrintVariables[tv: lf, put: h.tsOutStream, depth: depth, width: width, all: TRUE, breakBetweenItems: TRUE]; }; worldSwapDebug: BOOL; SetWorldSwapDebug: UserProfile.ProfileChangedProc = TRUSTED { wsd: BOOL = UserProfile.Boolean[key: "WorldSwapDebug", default: FALSE]; IF reason = firstTime THEN { worldSwapDebug _ wsd; IF NOT worldSwapDebug THEN AMEvents.GetEvents[WorldVM.LocalWorld[], NIL, EventHandler]; RETURN; }; IF wsd # worldSwapDebug THEN { -- user changed his WorldSwapDebug profile entry IF NOT wsd THEN AMEvents.GetEvents[WorldVM.LocalWorld[], NIL, EventHandler] ELSE AMEvents.StopEvents[WorldVM.LocalWorld[]]; worldSwapDebug _ wsd; }; }; TypeHelper: EvalQuote.EvalQuoteProc = TRUSTED { arg: InterpreterOps.Tree _ InterpreterOps.GetArg[tree, 1]; return _ AMBridge.TVForType[AMTypes.TVType[InterpreterOps.Eval[arg, head, target]]]; }; IRHelper: EvalQuote.EvalQuoteProc = TRUSTED { arg: InterpreterOps.Tree _ InterpreterOps.GetArg[tree, 1]; rope: ROPE _ InterpreterOps.TreeToName[arg]; IF rope = NIL THEN rope _ AMTypes.TVToName[InterpreterOps.Eval[arg, head, target]]; return _ AMMiniModel.GetInterfaceRecord[rope, InterpreterOps.WorldFromHead[head]]; }; SetIRHelper: EvalQuote.EvalQuoteProc = TRUSTED { h: Handle = NARROW[data, Handle]; return _ IRHelper[head, tree, target, data]; h.tsOutStream.PutRope["***Setting interface record context...\n"]; h.globalContext _ return; }; SetWorldHelper: EvalQuote.EvalQuoteProc = TRUSTED { context: AMModel.Context; world: WorldVM.World; h: Handle _ NARROW[data]; arg: InterpreterOps.Tree _ InterpreterOps.GetArg[tree, 1]; rope: ROPE _ InterpreterOps.TreeToName[arg]; IF rope = NIL THEN rope _ AMTypes.TVToName[InterpreterOps.Eval[arg, head, target]]; return _ AMTypes.GetEmptyTV[]; world _ WorldVM.GetWorld[rope]; h.tsOutStream.PutRope["***Setting World context...\n"]; h.tsOutStream.PutRope[WorldVM.WorldName[world]]; context _ AMModel.RootContext[world]; h.globalContext _ context; }; GlobalFrameHelper: EvalQuote.EvalQuoteProc = TRUSTED { arg: InterpreterOps.Tree _ InterpreterOps.GetArg[tree, 1]; rope: ROPE _ InterpreterOps.TreeToName[arg]; IF rope = NIL THEN rope _ AMTypes.TVToName[InterpreterOps.Eval[arg, head, target]]; return _ AMModel.MostRecentNamedContext[ rope, AMModel.RootContext[InterpreterOps.WorldFromHead[head]] ]; }; SetGlobalFrameHelper: EvalQuote.EvalQuoteProc = TRUSTED { h: Handle _ NARROW[data]; return _ GlobalFrameHelper[head, tree, target, data]; h.tsOutStream.PutRope["***Setting Global Frame context...\n"]; h.globalContext _ return; }; [] _ ViewerEvents.RegisterEventProc[proc: ViewerEvent, event: destroy]; Commander.Register[key: "///Commands/Interpreter", proc: NewInterpreter, doc: "Create a new interpreter tool"]; UserProfile.CallWhenProfileChanges[SetWorldSwapDebug]; END. TInterpreterToolImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Doug Wyatt, April 25, 1985 0:15:51 am PST Russ Atkinson (RRA) January 9, 1986 5:53:32 pm PST [cmd: Commander.Handle] [data: REF ANY, event: AMEvents.Event] RETURNS [outcome: AMEvents.Outcome] First, ask if this event is occurring under an interpreter. Ifso, nest the interpreter. NOTE assumption of order in FindInProgressEvaluation [PROCESS, nestingLevel] is in Evaluate, i.e. this event is occurring under an interpreter. Nest the event. some lower event of this tool is for a remote world Now do the recursive call of MainLoop. Return from recursive call of MainLoop. Now pop h's state (i.e. restore h). Won't raise any signals. [id: BreakID, clientData: REF ANY] [signal, args: TV ] AMEvents gave up on symbols; get the error message for BackStop.Call client bug; psbi and frame are valid. Too bloody long, so truncate it flushes viewer cache STOPGAP 'till a viewers bug is fixed Read/Eval/Print loop. FORK'd for each interpreter viewer. Called recursively if an error is raised during interpretation. the interpreter viewer was destroyed RETURN => event proc returns strip postfix !'s and ?'s Here if the interpreter viewer was destroyed. h.tsInStream will have been closed. PROC [data: REF] RETURNS [abort: BOOL]; Here to finalize an InterpreterObject (e.g. to break circular structures, close streams) [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] [msg: ROPE, severity: Severity] [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] START HERE [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] START HERE clear the break that caused this event clear the specified break START HERE [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] [world: WorldVM.World, clientData: REF] [parent: REF, clientData: REF, mouseButton: MouseButton, shift, control: BOOL] [msg: ROPE, severity: Severity] [viewer: Viewer, event: ViewerEvent, before: BOOL] RETURNS [abort: BOOL _ FALSE] [reason: ProfileChangeReason] [head: EvalHead, tree: Tree, target: Type, data: REF] RETURNS [return: TV] [head: EvalHead, tree: Tree, target: Type, data: REF] RETURNS [return: TV] [head: EvalHead, tree: Tree, target: Type, data: REF] RETURNS [return: TV] [head: EvalHead, tree: Tree, target: Type, data: REF] RETURNS [return: TV] [head: EvalHead, tree: Tree, target: Type, data: REF] RETURNS [return: TV] [head: EvalHead, tree: Tree, target: Type, data: REF] RETURNS [return: TV] START HERE ส,ฺ– "unit" style˜codešฯiœ™Kšœ ฯmœ7™BK™)K™2—K˜šฯk ˜ Kšœ Ÿœc˜qKšœ Ÿœภ˜ฮKšœ Ÿœ˜'KšœŸœˆ˜•KšœŸœ˜&KšœŸœ˜'KšœŸœ$Ÿœ#˜XKšœ ŸœE˜VKšœŸœ˜Kšœ Ÿœ˜Kšœ Ÿœ˜$Kšœ Ÿœ0˜?Kšœ Ÿœ˜*KšœŸœ˜!Kšœ Ÿœ˜(KšœŸœ=˜QKšœŸœM˜iKšŸœŸœPŸœŸœ˜eKšœŸœ˜KšœŸœ"˜/KšœŸœ8˜CKšœ Ÿœ ˜KšœŸœA˜NKšœŸœ˜#Kšœ Ÿœ˜.KšœŸœ'Ÿœ ˜?Kšœ ŸœŸœ˜Kšœ Ÿœ˜#KšœŸœ˜"Kšœ Ÿœ7˜EKšœ ŸœŸœ˜'KšœŸœ ˜Kšœ Ÿœ ˜2Kšœ Ÿœ˜%Kšœ ŸœF˜UKšœ Ÿœ7˜HKšœŸœ*˜7K˜—šœŸ œฯc#˜GKšŸœŸœŸœ ˜KšŸœมŸœฎ˜๘KšŸœ  ˜)KšœŸœŸœ˜˜KšŸœŸœ Ÿœ˜KšœŸœ˜K˜KšœŸœ# ˜@KšœŸœ,˜CK˜Kšœ Ÿœ%˜5KšœC˜CK˜KšœŸœ *˜JKšœŸœ˜K˜Kšœ Ÿœ&˜7šœŸœ ˜+K˜———šฯbœŸœ˜1Kšœ™Kš œŸœŸœ Ÿ  œŸœ˜DK˜K˜—šฯn œŸœŸœŸœ˜XKšœ ˜ šœ˜šŸœ Ÿ˜KšŸœ*˜.KšŸœ,˜0——KšœŸœ˜!šœŸœŸœ˜KšŸœ ŸœŸœŸœ˜šŸœ6Ÿ˜Kšœ˜—šœ˜Kšœ ŸœŸœŸœ˜9Kšœ˜—šœ˜KšœŸœŸœŸœ˜6Kšœ.˜.—šœ˜Kšœ ŸœŸœŸœ ˜0Kšœ8˜8—šœ˜Kš œ ŸœŸœŸœŸœŸœ˜HKšœ3˜3—šœ˜Kšœ˜KšŸœŸœŸœ9˜RKšœ˜—šœ˜Kšœ˜KšŸœŸœŸœ˜-Kšœ˜—šœ˜Kšœ˜KšŸœŸœŸœ˜)Kšœ˜—K˜Kšœ> ˜?šœ˜Kšœ˜KšŸœŸœ Ÿœ Ÿœ˜DKšœ;˜;—K˜Kšœ: ˜;šœ˜Kšœ˜Kš ŸœŸœ Ÿœ ŸœŸœŸœ˜NKšœ-˜-—K˜Kšœ7 ˜8šœ˜Kšœ˜KšŸœŸœ ŸœŸœ˜?Kšœ9˜9—K˜Kšœ5 ˜6šœ˜Kšœ˜KšŸœŸœŸœŸœ˜@Kšœ7˜7—K˜Kšœ5 ˜6šœ˜Kšœ˜Kš ŸœŸœŸœŸœŸœ˜DKšœ/˜/—K˜Kšœ1 ˜2šœ˜Kšœ˜Kš ŸœŸœŸœŸœŸœŸœ˜JKšœ˜—šœ˜K˜——š ะbn œŸœŸœŸœŸœŸœ˜PKšœ™KšœŸœ˜ KšœŸœŸœŸœ˜šŸœ ŸœŸ˜šœ ˜ Kšœ"™"KšœŸœ˜šŸœŸ˜šŸœ Ÿœ˜'Kšœ Ÿœ˜*——šŸœ Ÿ˜KšŸœ#˜'KšŸœ Ÿœ7˜G—K˜—Kšœ.˜.šœ ˜ Kšœ™šœŸœŸœŸœ˜Kšœ)˜)šŸœ8Ÿ˜>KšœD™DKš œŸœ!ŸœŸœŸœŸœ˜]—Kšœ˜—KšœŸœŸœ˜ Kšœ ˜ Kšœ Ÿœ˜K˜—šœ4˜4Kšœ%™%——KšœŸœŸœ˜šœ@˜@K˜—šœ˜šœŸœŸœŸœ˜Kšœ˜Kšœ,˜,Kšœ˜Kšœ'˜'Kšœ˜—KšœŸœŸœ˜ Kšœ ˜ KšœŸœ˜,šŸœŸœ˜"Kšœ™Kšœ6˜6K˜—K˜—K˜Kšœ˜K˜—šขœŸœ˜+Kšœ˜šขœŸœŸœŸœ˜=šœ˜Kšœ ˜ Kšœ ˜ šœ˜Kšœ<˜<——Kšœ˜—Kšœ-˜-Kšœ4˜4Kšœ;˜;Kšœ8˜8Kšœ6˜6Kšœ6˜6Kšœ2˜2Kšœ.˜.Kšœ0˜0KšŸœ ŸœŸœŸœ#˜RKšœ˜K˜—šข œŸœ#Ÿœ˜KšŸœŸœŸœ˜KšŸœ˜Kšœ˜—K˜šขœŸœŸœ&˜HKšŸœŸœŸœ˜KšœŸœ˜Kšœ˜Kšœ˜K˜—šขœŸœŸœ˜4KšŸœŸœŸœ˜KšœŸœ˜Kšœ˜K˜—š ขœŸœŸœ ŸœŸœ˜\KšŸœŸœŸœ˜KšŸœ'˜-Kšœ˜K˜—šขœŸœŸœ˜-KšŸœŸœŸœ˜KšœŸœ˜Kšœ˜K˜—šขœŸœŸœ˜/KšŸœŸœŸœ˜KšœŸœ˜Kšœ˜K˜—š ขœŸœŸœ ŸœŸœ˜˜>Kšœ6˜6KšŸœ˜Kšœ˜—Kšœ˜Kšœ˜K˜—šก œŸœ˜)Kšœ ŸœŸœ,Ÿœ™NKšœ Ÿœ˜'Kšœ+˜+Kšœ˜K˜—š ฃœŸœ ŸœŸœŸœ˜IKšŸœ ;˜BKšœ˜K˜—šฃœŸœ ŸœŸœŸœŸœŸœ˜SKšŸœ ;˜BKšœ˜K˜—š ขœŸœ ŸœŸœŸœ˜DKšŸœ ;˜BKšœ˜K˜—š ข œŸœŸœŸœŸœ˜EKšŸœ ;˜BKšœ˜K˜—šข œŸœŸœŸœŸœŸœŸœ˜OKšŸœ ;˜BKšœ˜K˜—š ข œŸœŸœŸœŸœ Ÿœ˜IKšŸœ ;˜BKšœ˜K˜—šก œŸœŸœŸœ˜.KšœŸœŸœ˜KšœŸœŸœŸœ˜šœŸœŸœŸœ˜KšœŸœ˜Kšœ Ÿœ˜šŸ˜šœ˜Kš œŸœ ŸœŸœŸœ!˜K—Kšœ>˜>KšŸœŸœŸœŸœ˜šŸœ ŸœŸ˜šœ ˜ Kšœ:˜:KšœN˜NKšœŸœ˜šŸœ ŸœŸ˜Kšœ+˜+KšŸœ˜—KšŸœŸœŸœ˜9Kšœ3˜3KšœI˜IKšœ/˜/K˜—KšŸœ˜—KšŸœ˜—Kšœ˜—K™K™ KšŸœŸœŸœ˜&Kšœ˜Kšœ6˜6K˜šŸœŸ˜ KšŸœ&˜*KšŸœ˜—Kšœ˜K˜—šก œŸœ˜)Kšœ ŸœŸœ,Ÿœ™NKšœ Ÿœ˜'šŸœ Ÿ˜Kšœ2˜2Kšœ7˜7KšŸœ˜—Kšœ˜K˜—šขœŸœŸœŸœ˜2KšœŸœŸœ˜KšœŸœŸœŸœ˜šœŸœŸœŸœ˜KšœŸœ˜Kšœ Ÿœ˜šŸ˜šœ˜Kš œŸœ ŸœŸœŸœ!˜K—Kšœ>˜>KšŸœŸœŸœŸœ˜šŸœ ŸœŸ˜šœ ˜ KšŸœŸœ%Ÿœ˜CKšœ˜KšœK˜KK˜—KšŸœ˜—KšŸœ˜—Kšœ˜—K™ KšŸœŸœŸœ˜&Kšœ˜Kšœ(˜(K˜šŸœŸ˜ KšŸœ&˜*KšŸœ˜—Kšœ˜K˜—šฃ œŸœŸœ-Ÿœ˜WKšœ ŸœŸœ˜KšœŸœ˜KšœŸœŸœŸœ˜K˜šœŸœŸœŸœ˜šŸœ˜šŸœ˜Kšœ&™&šŸœ Ÿ˜KšŸœ˜!šŸ˜šŸœ ŸœŸ˜šœ ˜ Kšœ˜šŸœŸœŸ˜Kšœ˜KšŸœ˜—šŸœ Ÿ˜KšŸœ:˜>KšŸœ˜—K˜—KšŸœ˜%———K˜—šŸœ˜Kšœ™KšœŸœ˜Kšœ Ÿœ˜šŸ˜šœ˜Kš œŸœ ŸœŸœŸœ!˜K—Kšœ>˜>KšŸœŸœŸœ3Ÿœ˜IšŸœ ŸœŸ˜šœ ˜ KšŸœŸœ%Ÿœ˜CšŸœŸœ˜Kšœ ˜ Kšœ˜K˜—K˜—KšŸœ˜—KšŸœ˜—K˜——Kšœ˜—K™ KšŸœŸœŸœ˜&Kšœ˜KšŸœ#˜%K˜šŸœŸœŸ˜KšœŸœŸœ3˜BKšœŸœŸœ˜$KšŸœŸœ:˜G—Kšœ˜K˜—šก œŸœ˜(Kšœ ŸœŸœ,Ÿœ™NKšœ Ÿœ˜'šŸœ Ÿ˜Kšœ=˜=KšœD˜DKšœ?˜?KšŸœŸœ˜—Kšœ˜K˜—šฃ œŸœ ŸœŸœ˜7šœŸœŸœŸœ˜Kš Ÿœ ŸœŸœŸœŸœŸœ˜4Kšœ˜KšœDŸœ˜JKšœ˜—KšŸœŸœŸœ˜&Kšœ,˜,Kšœ˜K˜—š ฃ œŸœŸœŸœŸœ˜7KšŸœŸœŸœ˜KšœŸœ˜šŸœŸ˜ ˜KšœŸœŸœ˜KšœŸœ ˜šŸœŸ˜Kšœ#˜#KšŸœŸœŸœ4Ÿœ˜LKšœ ˜ —KšŸœ˜KšŸœŸœŸœ1˜CK˜—KšœC˜C˜KšœŸœ ˜KšœŸœ˜šŸœ Ÿ˜KšœŸœ˜šŸœŸœ˜%Kšœ/˜/Kšœ0˜0KšŸœ˜—Kšœ ˜ šŸœ˜KšŸœ*Ÿœ˜5—Kšœ ˜ —KšŸœ˜Kšœ0˜0K˜——KšŸœ˜Kšœ˜K˜—š ฃœŸœŸœŸœ ŸœŸœ˜˜>Kšœ˜K˜—K™šœ ™ K˜KšœG˜GK˜Kšœo˜oK˜K˜6K˜—šŸœ˜K˜——…—bน