DIRECTORY AMBridge USING [RefFromTV, TVForReferent], AMTypes USING [TVType, TVToName, TypeClass, TVToType], BasicUserExec USING [Interface, InterfaceRec], BBInterp USING [EvalExpr, ParseExpr, Tree], BBContext USING [Context, ContextForGlobalFrame], BBEval USING [EvalHead], Commander USING [Lookup], Convert USING [ValueToRope], IO USING [CreateDribbleStream, EndOf, GetChar, GetIndex, GetOutputStreamRope, PeekChar, Put, PutChar, PutF, PutRope, PutTV, PutType, refAny, Reset, rope, ROPE, ROS, RIS, SetIndex, STREAM, Type, GetToken, GetRefAny, SkipOver, WhiteSpace], PPTree USING [Handle], PrintTV USING [PutClosure, PutProc], Rope USING [Cat, Concat, Equal, Fetch, Find, FromChar, IsEmpty, Length, Replace, Run, Substr], RTTypesBasic USING [EquivalentTypes], SymTab USING [Store], UserExec USING [HistoryEvent, ExecHandle, Expression, ExpressionRecord, RegisterCommand, CommandProc, TV, Viewer, ParseFailed, EvaluationFailed, GetStreams, CreateExpr, ErrorThisEvent, ReleaseStreams], UserExecExtras USING [], UserExecPrivate USING [EvalHeadData, CaptionForExec, GetPrivateStuff, GetEvalHead, DoesUserMean, ExecPrivateRecord, ExpressionPrivateRecord, Zone, CreateSubEvent, GetRestOfStream, ExecOwner, HistoryEventPrivateRecord] ; UserExecInterpImpl: CEDAR PROGRAM IMPORTS AMBridge, AMTypes, BBContext, BBInterp, Commander, Convert, IO, Rope, RTTypesBasic, SymTab, UserExec, UserExecPrivate EXPORTS UserExec, UserExecExtras, UserExecPrivate SHARES UserExecPrivate = BEGIN OPEN IO, UserExec, UserExecPrivate; ExecPrivateRecord: PUBLIC TYPE = UserExecPrivate.ExecPrivateRecord; HistoryEventPrivateRecord: PUBLIC TYPE = UserExecPrivate.HistoryEventPrivateRecord; ExpressionPrivateRecord: PUBLIC TYPE = UserExecPrivate.ExpressionPrivateRecord; Eval: CommandProc = { commandLine: ROPE = event.commandLine; len: INT; len _ Rope.Length[commandLine]; IF Rope.Length[commandLine] > 1 AND Rope.Fetch[commandLine, len - 2] = '! THEN { line: ROPE = Rope.Replace[base: commandLine, start: len - 2, len: 1]; subEvent: HistoryEvent = UserExecPrivate.CreateSubEvent[event: event, input: Rope.Concat["_ ", line]]; expr: Expression _ UserExec.CreateExpr[""]; privateExpr: REF ExpressionPrivateRecord _ expr.privateStuff; subEvent.commandLine _ line; subEvent.commandLineStream _ IO.RIS[line]; privateExpr.goForIt _ TRUE; subEvent.expression _ expr; TreatAsExpr[subEvent, exec, 1000, 1000, TRUE]; } ELSE TreatAsExpr[event, exec, defaultDepth, defaultWidth]; }; defaultDepth: PUBLIC INT _ 4; defaultWidth: PUBLIC INT _ 32; TreatAsExpr: PROC [event: HistoryEvent, exec: ExecHandle, depth: INT, width: INT, verbose: BOOL _ FALSE] = { out: STREAM = UserExec.GetStreams[exec].out; expr: Expression; privateExpr: REF ExpressionPrivateRecord; EvalEvent[event, exec]; expr _ event.expression; IF expr = NIL THEN RETURN; -- e.g. blank CR, perhaps you mean privateExpr _ expr.privateStuff; IF expr.numRtns = 1 AND (AMTypes.TypeClass[AMTypes.TVType[expr.value]] = globalFrame OR RTTypesBasic.EquivalentTypes[AMTypes.TVType[expr.value], CODE[BasicUserExec.Interface]]) THEN SetDefaultContextFromTV[exec: exec, expr: expr, out: out]; IF depth # 0 THEN { outRopeStream: STREAM = IO.ROS[]; out.PutF["*n"]; PrintValues[stream: IO.CreateDribbleStream[out, outRopeStream], expr: expr, depth: depth, width: width, verbose: verbose]; -- note that this creates a dribble stream for each new event. see earlier comments on allocation issues. privateExpr.valueRope _ outRopeStream.GetOutputStreamRope[]; -- why not simply return this as the msg argument. }; }; -- TreatAsExpr EvalEvent: PUBLIC PROC [event: HistoryEvent, exec: ExecHandle] = { private: REF ExecPrivateRecord = UserExecPrivate.GetPrivateStuff[exec]; eventPrivate: REF UserExecPrivate.HistoryEventPrivateRecord = event.privateStuff; commandLineStream: STREAM = event.commandLineStream; out: STREAM = UserExec.GetStreams[exec].out; expr: Expression _ event.expression; privateExpr: REF ExpressionPrivateRecord; eventNumRope, assignRope, line: ROPE; BEGIN ENABLE { EvaluationFailed => ERROR UserExec.ErrorThisEvent[event, msg]; ParseFailed => -- if failed to parse, and first token is a registered command, then perhaps user forgot he was in eval mode. { i: INT; inRopeStream: STREAM; secondToken: ROPE; IF (i _ Rope.Find[msg, "_"]) = -1 THEN UserExec.ErrorThisEvent[event, msg]; inRopeStream _ RIS[msg, inRopeStream]; inRopeStream.SetIndex[i + 1]; secondToken _ IO.GetToken[inRopeStream]; -- first thing following eval key. IF exec # NIL AND Commander.Lookup[secondToken].proc # NIL THEN { UserExecPrivate.DoesUserMean[rope: Rope.Substr[base: line, len: Rope.Length[line] - 1], exec: exec]; event.expression _ NIL; GOTO Out; }; ERROR UserExec.ErrorThisEvent[event, msg]; }; }; IO.SkipOver[commandLineStream, IO.WhiteSpace]; IF commandLineStream.EndOf[] THEN -- e.g. user just types eval or types cr after _. silly to give him an error. { RETURN; }; IF expr = NIL THEN event.expression _ expr _ CreateExpr[NIL]; privateExpr _ expr.privateStuff; IF commandLineStream.PeekChar[] = '_ THEN { [] _ commandLineStream.GetChar[]; IO.SkipOver[commandLineStream, IO.WhiteSpace]; expr.correctionMade _ TRUE; -- to reprint }; line _ UserExecPrivate.GetRestOfStream[commandLineStream]; expr.rope _ line; expr.dontCorrect _ event.dontCorrect; eventNumRope _ Convert.ValueToRope[[signed[eventPrivate.eventNum]]]; assignRope _ Rope.Cat["&", eventNumRope, " _ "]; ParseTree[assignRope: assignRope, input: line, expr: expr]; [expr.value, expr.numRtns] _ EvalTree[expr, exec]; IF expr.correctionMade THEN { expr.rope _ ReprintTree[privateExpr.tree]; event.input _ Rope.Concat["_ ", expr.rope]; }; privateExpr.tree _ (NARROW[privateExpr.tree, PPTree.Handle]).son[2]; -- the tree to be stored is without the & assignment GOTO Exit; EXITS Exit => { eventPrivate.state _ completed; }; Out => NULL END; }; -- EvalEvent StoreInSymTab: PUBLIC PROC [value: TV, event: HistoryEvent, exec: ExecHandle] = { evalHead: BBEval.EvalHead = UserExecPrivate.GetEvalHead[exec]; eventPrivate: REF UserExecPrivate.HistoryEventPrivateRecord = event.privateStuff; eventPrivate.value _ value; [] _ SymTab.Store[x: evalHead.specials, key: Rope.Cat["&", Convert.ValueToRope[[signed[eventPrivate.eventNum]]]], val: value]; [] _ SymTab.Store[x: evalHead.specials, key: "&", val: value]; }; PrintValues: PROCEDURE[stream: STREAM, expr: Expression, depth: INT _ -1, width: INT _ -1, verbose: BOOLEAN _ FALSE] = { IF expr.numRtns = 0 THEN stream.PutRope["{does not return a value}"] ELSE { typ: Type = AMTypes.TVType[expr.value]; SELECT AMTypes.TypeClass[typ] FROM type => stream.PutType[type: AMTypes.TVToType[expr.value], depth: depth, width: width, verbose: TRUE]; -- if type is REF or POINTER, verbose= TRUE prints range. ENDCASE => stream.PutTV[tv: expr.value, depth: depth, width: width, verbose: verbose]; }; }; -- of PrintValues EvalExpr: PUBLIC PROC [expr: Expression, exec: ExecHandle, viewer: Viewer _ NIL] RETURNS[value: TV, numRtns: INT] = { oldExecOwner: UNSAFE PROCESS; privateExpr: REF ExpressionPrivateRecord = expr.privateStuff; {ENABLE UNWIND => IF exec # NIL AND oldExecOwner # UserExecPrivate.ExecOwner[exec] THEN UserExec.ReleaseStreams[exec]; -- somebody, e.g. in DWIM, did a GetStreams without releasing (this is ok to do). IF exec # NIL THEN oldExecOwner _ UserExecPrivate.ExecOwner[exec]; IF privateExpr.tree = NIL THEN ParseTree[input: expr.rope, expr: expr]; [value, numRtns] _ EvalTree[expr, exec, viewer]; expr.value _ value; expr.numRtns _ numRtns; IF expr.correctionMade THEN expr.rope _ ReprintTree[privateExpr.tree]; IF exec # NIL AND oldExecOwner # UserExecPrivate.ExecOwner[exec] THEN UserExec.ReleaseStreams[exec]; -- somebody, e.g. in DWIM, did a GetStreams without releasing (this is ok to do). }; }; -- of EvalExpr CreateExpr: PUBLIC PROCEDURE [rope: ROPE, dontCorrect: BOOL _ FALSE] RETURNS [Expression] = { RETURN[UserExecPrivate.Zone.NEW[UserExec.ExpressionRecord _ [ rope: rope, dontCorrect: dontCorrect, privateStuff: UserExecPrivate.Zone.NEW[UserExecPrivate.ExpressionPrivateRecord _ []] ]] ]; }; ReprintTree: PROC [tree: BBInterp.Tree, outRopeStream: IO.STREAM _ NIL] RETURNS[value: ROPE] = { r: ROPE = "{tree for: "; i: INT; IF outRopeStream = NIL THEN outRopeStream _ IO.ROS[] ELSE outRopeStream.Reset[]; outRopeStream.Put[refAny[(NARROW[tree, PPTree.Handle]).son[2]]]; -- the tree without the & assignment value _ outRopeStream.GetOutputStreamRope[]; IF (i _ Rope.Find[value, "{tree for: "]) # -1 THEN { value _ Rope.Substr[base: value, start: Rope.Length[r]]; value _ Rope.Substr[base: value, len: Rope.Length[value] - 1]; -- strip off } }; WHILE Rope.Fetch[base: value, index: i _ (Rope.Length[value] - 1)] = ' DO value _ Rope.Substr[base: value, len: i]; ENDLOOP; }; ParseTree: PROC [input: ROPE, assignRope: ROPE _ NIL, expr: Expression] = { outRopeStream: STREAM = IO.ROS[]; inRopeStream: STREAM = IO.RIS[""]; privateExpr: REF UserExecPrivate.ExpressionPrivateRecord = expr.privateStuff; { outRopeStream.Reset[]; expr.rope _ input; privateExpr.tree _ BBInterp.ParseExpr[expr: Rope.Concat[IF assignRope = NIL THEN "& _ " ELSE assignRope, input], errout: PrintTV.PutClosure[proc: ErrorOut, data: outRopeStream] ]; IF privateExpr.tree = NIL THEN -- look at error message to see if anything can be done, e.g. fix up $( and $[ to be LIST[]; { rope: ROPE _ outRopeStream.GetOutputStreamRope[]; pos: INT _ Rope.Find[rope, "*^*"]; char: CHARACTER; IF pos = -1 THEN GOTO Failed; IF Rope.Fetch[rope, pos + 4] = '$ AND (char _ Rope.Fetch[rope, pos + 5]) = '( OR char = '[ THEN { pos: INT _ Rope.Find[input, Rope.Concat["$", Rope.FromChar[char]]]; ref: REF ANY; PrintList: PROC [stream: IO.STREAM, ref: REF ANY] = { WITH ref SELECT FROM l: LIST OF REF ANY => {stream.PutRope["LIST["]; FOR lst: LIST OF REF ANY _ l, lst.rest UNTIL lst = NIL DO PrintList[stream, lst.first]; IF lst.rest # NIL THEN stream.PutRope[", "]; ENDLOOP; stream.PutChar[']]; }; ENDCASE => stream.Put[refAny[ref]]; }; IF pos = -1 THEN GOTO Failed; [] _ RIS[rope: input, oldStream: inRopeStream]; inRopeStream.SetIndex[pos + 1]; ref _ IO.GetRefAny[inRopeStream]; outRopeStream.Reset[]; PrintList[stream: outRopeStream, ref: ref]; input _ Rope.Replace[base: input, start: pos, len: inRopeStream.GetIndex[] - pos, with: outRopeStream.GetOutputStreamRope[]]; expr.correctionMade _ TRUE; ParseTree[input, assignRope, expr]; } ELSE GOTO Failed; }; RETURN; EXITS Failed => ERROR ParseFailed[expr: expr, msg: outRopeStream.GetOutputStreamRope[]]; }; }; -- of ParseTree ErrorOut: PrintTV.PutProc -- [data: REF, c: char] -- = {NARROW[data, IO.STREAM].PutChar[c]}; EvalTree: PROC [expr: Expression, exec: ExecHandle, viewer: Viewer _ NIL] RETURNS[value: TV, numRtns: INTEGER] = { privateExpr: REF ExpressionPrivateRecord = expr.privateStuff; [value, numRtns] _ BBInterp.EvalExpr[privateExpr.tree, UserExecPrivate.GetEvalHead[exec: exec, viewer: viewer, expr: expr]]; }; SetDefaultContext: UserExec.CommandProc = { ENABLE UserExec.EvaluationFailed => ERROR UserExec.ErrorThisEvent[event, msg]; commandLineStream: STREAM = event.commandLineStream; out: STREAM = UserExec.GetStreams[exec].out; name: ROPE; expr: UserExec.Expression; name _ IO.GetToken[commandLineStream]; IF NOT name.IsEmpty[] THEN [] _ EvalExpr[expr: expr _ CreateExpr[name], exec: exec]; SetDefaultContextFromTV[exec, expr, out]; }; SetDefaultContextFromTV: PROC [exec: UserExec.ExecHandle, expr: UserExec.Expression, out: STREAM] = { private: REF ExecPrivateRecord = exec.privateStuff; gf: TV; defaultInterface, moduleName: ROPE; globalContext: BBContext.Context _ NIL; evalHead: BBEval.EvalHead = UserExecPrivate.GetEvalHead[expr: NIL, exec: exec]; evalHeadData: REF UserExecPrivate.EvalHeadData = NARROW[evalHead.data]; IF expr = NIL THEN NULL ELSE IF AMTypes.TypeClass[AMTypes.TVType[expr.value]] = globalFrame THEN gf _ expr.value ELSE TRUSTED { interFace: REF BasicUserExec.Interface = NARROW[AMBridge.RefFromTV[expr.value]]; defaultInterface _ interFace^^; }; IF gf # NIL THEN { len: INT _ Rope.Length[expr.rope]; moduleName _ AMTypes.TVToName[gf]; WHILE IO.WhiteSpace[Rope.Fetch[expr.rope, len - 1]] = sepr DO -- in most cases, expr.rope will have an extra space or cr at end (but not when it has been corrected) len _ len - 1; ENDLOOP; defaultInterface _ Rope.Substr[base: expr.rope, len: len]; IF Rope.Equal[moduleName, defaultInterface] OR Rope.Run[s1: moduleName, s2: defaultInterface, case: FALSE] < Rope.Length[defaultInterface] THEN { -- second check is to handle situation where the value of an expression is a global frame, e.g. &9 globalContext _ BBContext.ContextForGlobalFrame[gf]; defaultInterface _ NIL; } ELSE TRUSTED { -- user typed in name of interface, for which there happened to also be an impl, so Russ converted it, e.g. type in IO, get IOImpl. expr.value _ AMBridge.TVForReferent[NEW[BasicUserExec.Interface _ NEW[BasicUserExec.InterfaceRec _ [defaultInterface]]]]; -- so right thing is printed out } }; evalHead.globalContext _ globalContext; evalHeadData.defaultInterface _ defaultInterface; IF private.evalMode AND private.actionAreaData = NIL THEN [] _ UserExecPrivate.CaptionForExec[exec]; IF globalContext # NIL THEN out.PutF["*n*mdefault global context changed to: %g*s", rope[moduleName]] ELSE IF defaultInterface # NIL THEN out.PutF["*n*mdefault interface changed to: %g*s", rope[defaultInterface]] ELSE out.PutF["*n*mdefault global context/interface no longer set*s"]; }; UserExec.RegisterCommand["_", Eval, "Treat the remainder of the input line as a mesa expression to be evaluated.", "Treat the remainder of the input line as a mesa expression to be evaluated. Evaluate the expression and print its value. If the expression is terminated with !, print value showing the referents of all REFs and POINTERs to an unlimited depth. To call a registered command or load a file, backspace over the _."]; UserExec.RegisterCommand["SetContext", SetDefaultContext, "(Re)Set default context.", "SetContext {name of module or interface} sets default context to given name. SetContext{cr} clears default context."]; END. -- of UserExecInterpImpl Hmiscellaneous procedures related to interpreting expressions by the userexec Last Edited by: Warren Teitelman, April 17, 1983 8:08 pm BBEval: so can access private files in EvalTree UserExecPrivate; Zone connecting concrete and opaque types so can access continuation, idRope in TreatAsExpr, and evalMode in SetGlobalContextFromTV to access state and eventNum in TreatAsExpr so can access tree, etc. in TreatAsExpr interpreting expressions IF private # NIL THEN private.continuation _ TRUE; took this out because the event might have consisted of just a comment, and might want this in the history. the expense is an extra, empty event if user types _{cr}. IF inRopeStream.PeekChar[] = '{ THEN -- evaluate in context of some other work area. { token, in: ROPE; UNTIL Rope.Equal[(token _ IO.GetToken[inRopeStream]), "}"] DO in _ token; ENDLOOP; FOR l: LIST OF ExecHandle _ UserExecPrivate.execHandleList, l.rest UNTIL l = NIL DO private: REF ExecPrivateRecord = l.first.privateStuff; IF Rope.Equal[private.idRope, in] THEN {event.props _ Atom.PutPropOnList[propList: event.props, prop: $WorkArea, val: l.first]; EXIT}; REPEAT FINISHED => ERROR UserExecPrivate.ErrorThisEvent[Rope.Concat["No Work Area with name ", in]]; ENDLOOP; }; IF expr.numRtns > 0 THEN {IF private # NIL THEN [] _ SymTab.Store[x: BBEval.GetSymTab[], key: Rope.Cat["&", private.id, eventNumRope], val: expr.value]; }; makes the & variable associated with event have as its value the indicated tv. For use for those commands which return a value, e.g. walkstack, showframe, etc. ELSE IF expr.value = History.notAnExpression THEN NULL -- i.e. runs a program. does evaluation when you dont have an event. called by execprocessinput to evaluate promptforms, executing forms.. parsing, evaluating, and printing trees parses input rope. does not know about events. sets CorrectionMade in event if the tree that it produces does not correspond to the input. Setting default contexts Edited on January 28, 1983 4:30 pm, by Teitelman fixed SetContext not to create new caption if in action area changes to: SetDefaultContextFromTV Edited on February 4, 1983 3:11 pm, by Teitelman changes to: SetDefaultContextFromTV Edited on March 6, 1983 5:44 pm, by Teitelman changes to: Eval, defaultDepth, defaultWidth, TreatAsExpr, PrintValues, DIRECTORY, TreatAsExpr Edited on March 10, 1983 2:51 am, by Teitelman changes to: DIRECTORY, EXPORTS Edited on March 24, 1983 4:27 pm, by Teitelman removed storing of & expressions in global symbols table as well as local symbol table changes to: EvalEvent, DIRECTORY, IMPORTS Edited on April 6, 1983 11:07 am, by Teitelman changes to: StoreInSymTab, PrintValues, DIRECTORY, IMPORTS, EvalEvent Edited on April 8, 1983 1:30 pm, by Teitelman changes to: DIRECTORY, SetDefaultContextFromTV Edited on April 17, 1983 8:08 pm, by Teitelman changes to: DIRECTORY, IMPORTS, EvalEvent Κn– "Cedar" style˜J˜JšΟcL™LJ™9šΟk ˜ Jšœ žœ˜*Jšœžœ)˜6Jšœžœ˜.Jšœ žœ˜+Jšœ žœ"˜1Jšœžœ ˜Jšœ žœ ˜Jšœžœ˜Jš žœžœ’žœžœžœ žœ3˜νJšœžœ ˜Jšœžœ˜$JšœžœT˜^Jšœ žœ˜%Jšœžœ ˜Jšœ žœXžœa˜ΙJšœžœ˜JšœžœΔ˜ΩJ˜J˜—JšΠblœžœžœ˜#J˜Jšžœ=žœ8˜~J˜Jšžœ,˜3J˜šžœ˜Jšœ0™0Jšœ™—J˜Jšœžœžœžœ˜+headšœ$™$šΟnœžœžœ%˜CJ™Y—J˜š œžœžœ-˜SJšœ+™+—š œžœžœ+˜OJ™(——šœ™š œž˜Jšœ žœ˜&Jšœžœ˜ Jšœ˜šžœžœ'žœ˜O˜Jšœžœ;˜EJšœf˜fJ˜+Jšœ žœ-˜=Jšœ˜Jšœžœžœ˜*Jšœžœ˜J˜Jšœ(žœ˜.J˜——Jšžœ7˜;Jšžœ˜—J˜Jš  œžœžœ˜Jš  œžœžœ˜J˜š   œžœ0žœ žœ žœžœ˜mJšœžœ Πbo œ ˜,Jšœ˜Jšœ žœ˜)Jšœ˜Jšœ˜Jš žœžœžœžœ"˜=Jšœ ˜ šžœž˜Jšœ<˜Πbc2œ˜rJ˜——Jšœ˜—J˜š  œž œ-˜CJšœ žœ;˜GJšœžœ@˜QJšœžœ˜4Jšœžœ ‘ œ ˜,Jšœ$˜$Jšœ žœ˜)Jšœ žœ˜%J˜Jšž˜šž˜Jšœžœ%˜>šœm˜}šœ˜Jšœžœ˜Jšœžœ˜Jšœ žœ˜Jšžœ žœ%˜KJšœžœ˜'J˜Jšœ)"˜Kš žœžœžœ&žœžœ˜BJ˜dJšœžœ˜Jšžœ˜ J˜—Jšžœ%˜*J˜——J˜J˜—J˜.šžœžœM˜oJšœ˜Jšžœ žœžœžœ¨™ΩJšžœ˜J˜—Jšžœžœžœ&žœ˜=Jšœ ˜ šžœ#ž˜)˜Jšœ!˜!Jšœ.˜.Jšœžœ ˜)J˜——šžœžœ/™Tšœ™Jšœ žœ™šžœ6ž™=J™ Jšžœ™—š žœžœžœ5žœžœž™SJšœ žœ*™6šžœ ž™&J™XJšžœ™—Jšž™JšžœžœL™]Jšžœ™—J™——Jšœ:˜:J˜J˜%JšœD˜DJšœ0˜0J˜;J˜2šžœž˜Jšœ*˜*Jšœ+˜+Jšœ˜—Jšœžœ+5˜zJšžœ˜ šž˜˜šœ˜šžœžœ™Jšœžœ žœžœi™J™—J˜J˜——Jšœž˜ —Jšžœ˜Jšœ ˜—J˜š  œž œ žœ,˜QJšœ ™ Jšœ>˜>Jšœžœ@˜QJ˜Jšœ~˜~Jšœ>˜>J˜—J˜š  œž œ žœžœžœžœžœ˜xJšžœžœ,˜DJš žœžœ&žœžœ™Nšž˜J˜'šžœž˜"Jšœ`žœ<˜£JšžœR˜YJ˜—J˜—Jšžœ˜—˜Jšr™r—J˜š œžœžœ7žœžœžœ žœ˜uJšœžœ˜Jšœ žœ-˜=šž˜Jš žœžœžœ0žœ ‘œQ˜Ά—Jšžœžœžœ0˜BJšžœžœžœ+˜IJ˜0Jšœ˜Jšœ˜Jšžœžœ+˜FJš žœžœžœ0žœ ‘œRœ˜·Jšœ˜Jšœ˜—J˜š  œžœž œžœžœžœžœ˜]šžœžœ˜=Jšœ ˜ Jšœ˜Jšœ#žœ.˜TJšœ˜Jšœ˜—Jšœ˜J˜——™'š   œžœ&žœž œžœžœ˜`Jšœžœ˜Jšœžœ˜Jš žœžœžœžœžœžœ˜PJšœžœ!$˜eJ˜,šžœ,ž˜4Jšœ8˜8JšœN˜NJšœ˜—•StartOfExpansion [base: ROPE, index: INT _ 0]šžœCž˜JJ˜)Jšžœ˜—J˜—˜JšŠ™Š—š   œžœ žœžœžœ˜KJšœžœžœ˜!Jšœžœžœ ˜"Jšœ žœ=˜MJ˜šž˜J˜J˜Jš œ8žœžœžœžœX˜΄šžœžœžœ]˜|šž˜Jšœžœ'˜1Jšœžœ˜"Jšœž œ˜Jšžœ žœžœ˜šžœ žœ)žœ ž˜_šž˜Jšœžœ;˜CJšœžœžœ˜ š   œžœ žœžœžœžœ˜5šžœžœž˜š œžœžœžœžœ˜J˜šžœžœžœžœžœžœžœž˜9J˜Jšžœ žœžœ˜,Jšžœ˜—J˜—Jšžœ˜#—J˜—J˜Jšžœ žœžœ˜Jšœžœ'˜/J˜J˜!J˜J˜+J˜~Jšœžœ˜J˜#Jšž˜——Jšžœžœ˜Jšžœ˜——Jšžœ˜Jšž˜Jšœ žœžœ,˜RJšžœ˜—Jšœ˜—J˜Jš  œœžœžœžœ˜^J˜š  œžœ7žœžœžœ žœ˜rJšœ žœ-˜=Jšœ|˜|Jšœ˜——™š œΠckœ˜-Jšžœžœ%˜NJšœžœ˜4Jšœžœ ‘ œ ˜,Jšœžœ˜ Jšœ˜Jšœ&˜&Jšžœžœžœ:˜TJšœ*˜*J˜—J˜š œžœ>žœ˜gJšœ žœ'˜3Jšœ˜Jšœžœ˜#Jšœ#žœ˜'Jšœ>žœ˜OJšœžœ žœ˜GJ˜Jšžœžœžœž˜Jšžœžœ=žœ˜Xšžœ˜Jšœ žœžœ!˜PJšœ˜J˜—J˜šžœžœž˜Jšœžœ˜"Jšœ"˜"šžœžœ3žœf˜₯J˜Jšžœ˜—Jšœ:˜:š žœ*žœ6žœ"žœc˜φJšœ4˜4Jšœžœ˜—šžœžœ˜Jšœƒ˜„Jšœ$žœžœžœ' ˜›J˜—J˜—J˜Jšœ'˜'Jšœ1˜1Jšžœžœžœžœ+˜dJšžœžœžœJ˜eJšžœžœžœK˜nJšžœB˜FJ˜J˜——J˜J˜¬J˜J˜ΝJ˜Jšžœ˜J˜J˜J˜™0J™