DIRECTORY AMBridge, AMModel, AMTypes, BackStop, BBUrpEval, CBinary, Commander, CommandTool, EvalQuote, FS, Interpreter, InterpreterOps, InterpreterPrivate, IntHashTable, IO, List, PPLeaves, PPP1, PPTree, PPTreeOps, PrincOps, PrincOpsUtils, PrintTV, Process, ProcessProps, Real, Rope, SafeStorage, StatementInterpreter, StatementInterpreterPrivate, SymTab, WorldVM; StatementCommands: CEDAR PROGRAM IMPORTS AMBridge, AMModel, AMTypes, BackStop, BBUrpEval, CBinary, Commander, CommandTool, EvalQuote, FS, InterpreterOps, InterpreterPrivate, IntHashTable, IO, List, PPP1, PPTreeOps, PrincOpsUtils, Process, ProcessProps, Real, Rope, SafeStorage, StatementInterpreter, StatementInterpreterPrivate, SymTab, WorldVM EXPORTS StatementInterpreter, StatementInterpreterPrivate = BEGIN OPEN StatementInterpreter, StatementInterpreterPrivate; SymbolTable: TYPE = SymTab.Ref; empty: PUBLIC TV _ AMTypes.GetEmptyTV[]; typeType: PUBLIC Type; Exit: PUBLIC ERROR = CODE; Loop: PUBLIC ERROR = CODE; GetReturnFields: PUBLIC SIGNAL RETURNS [fields: Fields] = CODE; Return: PUBLIC ERROR [fields: Fields] = CODE; GetResumeFields: PUBLIC SIGNAL RETURNS [fields: Fields] = CODE; Resume: PUBLIC ERROR [fields: Fields] = CODE; GoTo: PUBLIC ERROR [label: ROPE] = CODE; DecideSignal: PUBLIC ERROR [decision: BasicSignalDecisionType] = CODE; ProcTypeBufferList: TYPE = LIST OF ProcTypeBuffer; ProcTypeBuffer: TYPE = RECORD [ procType: Type, fileName: ROPE, free: DummyStuffList _ NIL ]; procTypeBuffers: ProcTypeBufferList _ NIL; prefix: ROPE = "Dummy"; prefixLength: INT = prefix.Length[]; RegisterDummys: PUBLIC PROC [fileName: ROPE, gfh: PrincOps.GlobalFrameHandle] = { fullFile: ROPE = FS.ExpandName[fileName].fullFName; gftv, globals: TV; globalsType: Type; TRUSTED {gftv _ AMBridge.TVForGFHReferent[gfh]}; globals _ AMTypes.Globals[gftv]; globalsType _ AMTypes.TVType[globals]; FOR i: INT IN [1 .. AMTypes.NComponents[globalsType]] DO ds: DummyStuff; name: ROPE = AMTypes.IndexToName[globalsType, i]; tv: TV; type: Type; bl: ProcTypeBufferList; IF Rope.Run[s1: name, s2: prefix] # prefixLength THEN LOOP; tv _ AMTypes.IndexToTV[globals, i]; type _ AMTypes.TVType[tv]; SELECT AMTypes.UnderClass[type] FROM procedure => NULL; ENDCASE => LOOP; TRUSTED { ds _ NEW [DummyStuffPrivate _ [ proc: AMBridge.TVToProc[tv], asTV: tv]]; }; bl _ FindProcBuffer[type]; IF bl = NIL THEN bl _ procTypeBuffers _ CONS[[type, fullFile], procTypeBuffers]; bl.first.free _ CONS[ds, bl.first.free]; ENDLOOP; }; FindProcBuffer: PROC [procType: Type] RETURNS [bl: ProcTypeBufferList] = { FOR bl _ procTypeBuffers, bl.rest WHILE bl # NIL AND NOT SafeStorage.EquivalentTypes[procType, bl.first.procType] DO NULL ENDLOOP; }; FindConsdProcBuffer: PROC [l: Lambda] RETURNS [bl: ProcTypeBufferList] = { FOR bl _ procTypeBuffers, bl.rest WHILE bl # NIL AND NOT (FTConform[l.args, AMTypes.Domain[bl.first.procType]] AND FTConform[l.rets, AMTypes.Range[bl.first.procType]]) DO NULL ENDLOOP; }; FTConform: PROC [fields: Fields, recordType: Type] RETURNS [conform: BOOL] = { rLen: INT = SELECT AMTypes.UnderClass[recordType] FROM nil => 0, record, structure => AMTypes.NComponents[recordType], ENDCASE => ERROR; IF rLen # fields.length THEN RETURN [FALSE]; FOR i: INT IN [0 .. fields.length) DO rName: ROPE = AMTypes.IndexToName[recordType, i+1]; fName: ROPE = fields[i].name; IF rName.Length[] # 0 AND fName.Length[] # 0 AND NOT rName.Equal[fName] THEN RETURN [FALSE]; IF NOT SafeStorage.EquivalentTypes[fields[i].type, AMTypes.IndexToType[recordType, i+1]] THEN RETURN [FALSE]; ENDLOOP; conform _ TRUE; }; procDataMap: IntHashTable.Table _ IntHashTable.Create[]; AllocProc: PROC [procType: Type] RETURNS [ds: DummyStuff] = { bl: ProcTypeBufferList _ FindProcBuffer[procType]; IF bl = NIL THEN RETURN [NIL]; IF bl.first.free = NIL THEN { [] _ CommandTool.Run[bcdName: bl.first.fileName, runEvenIfAlreadyRun: TRUE]; }; IF bl.first.free = NIL THEN RETURN [NIL]; ds _ bl.first.free.first; bl.first.free _ bl.first.free.rest; IF NOT procDataMap.Store[LOOPHOLE[ds.proc, CARDINAL], ds] THEN ERROR; }; AllocConsdProc: PROC [l: Lambda] RETURNS [ds: DummyStuff] = { bl: ProcTypeBufferList _ FindConsdProcBuffer[l]; IF bl = NIL THEN RETURN [NIL]; IF bl.first.free = NIL THEN { [] _ CommandTool.Run[bcdName: bl.first.fileName, runEvenIfAlreadyRun: TRUE]; }; IF bl.first.free = NIL THEN RETURN [NIL]; ds _ bl.first.free.first; bl.first.free _ bl.first.free.rest; IF NOT procDataMap.Store[LOOPHOLE[ds.proc, CARDINAL], ds] THEN ERROR; }; GetStuff: PUBLIC PROC [dummy: PROCANY] RETURNS [ds: DummyStuff] = { ds _ NARROW[procDataMap.Fetch[LOOPHOLE[dummy, CARDINAL]].value]; }; NarrowToSymbolTable: PUBLIC PROC [ra: REF ANY] RETURNS [st: SymbolTable] = { st _ NARROW[ra]; }; commandProcResultType: Type = AMTypes.GroundStar[AMTypes.Range[CODE[Commander.CommandProc]]]; StatementCommand: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] --Commander.CommandProc-- = { blockAsRope: ROPE _ Rope.Cat["{", cmd.commandLine]; len: INT = blockAsRope.Length[]; errorRope: ROPE; head: InterpreterOps.EvalHead = NARROW[List.Assoc[$EvalHead, ProcessProps.GetPropList[]]]; context: AMModel.Context; symTab: SymbolTable; resultsTV: TV = AMTypes.New[commandProcResultType]; IF len < 1 THEN RETURN; IF blockAsRope.Fetch[len-1] = '\n THEN blockAsRope _ blockAsRope.Substr[len: len - 1]; IF head = NIL THEN TRUSTED {context _ AMModel.RootContext[WorldVM.LocalWorld[]]} ELSE { context _ head.context; IF context = NIL THEN TRUSTED {context _ AMModel.RootContext[InterpreterOps.WorldFromHead[head]]}; }; TRUSTED {symTab _ NarrowToSymbolTable[List.Assoc[$SymTab, cmd.propertyList]]}; IF symTab = NIL THEN { symTab _ SymTab.Create[]; [] _ List.PutAssoc[key: $SymTab, val: symTab, aList: cmd.propertyList]; }; [] _ symTab.Store["commandResults", resultsTV]; errorRope _ InterpretStatement[blockAsRope, context, symTab]; IF errorRope # NIL THEN { cmd.out.PutRope[Rope.Cat["Error: ", errorRope, "\n"]]; result _ $Failure; RETURN}; TRUSTED { result _ AMBridge.TVToRef[AMTypes.IndexToTV[resultsTV, 1]]; msg _ NARROW[AMBridge.TVToRef[AMTypes.IndexToTV[resultsTV, 2]]]; }; }; InterpretStatement: PUBLIC PROC [blockAsRope: ROPE, context: Context _ NIL, symTab: SymbolTable _ NIL, abort: InterpreterOps.AbortClosure _ Interpreter.nilAbortClosure] RETURNS [errorRope: ROPE] = { Inner: PROC = { bodyTree: Tree _ ParseBlock[blockAsRope, errorStream]; Interp[ asTree: bodyTree, head: InterpreterOps.NewEvalHead[ context: context, specials: symTab, helpFatalClosure: [myHelpFatal, errorStream], abortClosure: abort], nest: FALSE !FatalInterpreterError => {errorStream.PutRope[msg]; CONTINUE}]; }; errorStream: IO.STREAM _ IO.ROS[]; IF context = NIL THEN TRUSTED {context _ AMModel.RootContext[WorldVM.LocalWorld[]]}; IF symTab = NIL THEN symTab _ SymTab.Create[]; errorStream.PutRope[BackStop.Call[Inner]]; errorRope _ IO.RopeFromROS[errorStream]; }; FatalInterpreterError: ERROR[msg: ROPE] = CODE; myHelpFatal: PROC [data: REF, head: EvalHead, parent: Tree, msg: ROPE] --InterpreterOps.HelpFatal-- = TRUSTED { ERROR FatalInterpreterError[msg]; }; First: PROC [nn: PPTree.NodeName, in: Tree] RETURNS [out: Tree] = { IF in = NIL THEN RETURN [NIL]; WITH in SELECT FROM n: Node => { IF n.name = nn THEN RETURN [n]; FOR i: NAT IN [1 .. n.sonLimit) DO out _ First[nn, n.son[i]]; IF out # NIL THEN RETURN; ENDLOOP}; ENDCASE; out _ NIL}; HandleEnable: PROC [inner: PROC, data: REF ANY, call, catch: Tree, head: EvalHead] --InterpreterPrivate.ErrorHandler-- = {Enable[NARROW[catch], head, inner]}; Interp: PUBLIC PROC [asTree: Tree, head: EvalHead, nest: BOOL _ TRUE] = { Inner: PROC = {InterpNoProps[NARROW[asTree], head, nest]}; InterpreterPrivate.EnableBlock[head: head, handler: HandleEnable, data: NIL]; ProcessProps.AddPropList[List.PutAssoc[$EvalHead, head, NIL], Inner]; }; InterpNoProps: PUBLIC PROC [tree: Tree, head: EvalHead, nest: BOOL _ TRUE] = { IF tree # NIL THEN WITH tree SELECT FROM node: Node => { SELECT node.name FROM list => FOR i: NAT IN[1 .. node.sonLimit) DO InterpNoProps[node.son[i], head]; ENDLOOP; assignx, assign, extractx, extract => [] _ EvalExpr[node, head]; apply, signal, error => [] _ EvalExpr[node, head]; body => EvalBody[node, head, nest]; block => EvalBlock[node, head, nest]; if => EvalIf[node, head]; do => EvalDo[node, head]; label => EvalLabelled[node, head]; return => EvalReturn[node, head]; resume => EvalResume[node, head]; exit => ERROR Exit; syserror => { SIGNAL BackStop.SuspendBackStop[]; ERROR; }; loop => ERROR Loop; goto => { name: PPLeaves.HTIndex _ NARROW[node.son[1]]; ERROR GoTo[name.name]}; reject => ERROR DecideSignal[Reject]; retry => ERROR DecideSignal[Retry]; continue => ERROR DecideSignal[Continue]; null => NULL; enable => { EvalInner: PROC = {InterpNoProps[NARROW[node.son[2]], head]}; Enable[NARROW[node.son[1]], head, EvalInner]; }; open => EvalOpen[node, head, nest]; ENDCASE => GOTO NYI; EXITS NYI => BBUrpEval.UrpFatal[head, node, Rope.Cat["Not Implemented: ", nodeNames[node.name]]]; }; ENDCASE => [] _ EvalExpr[tree, head]; }; EvalExpr: PUBLIC PROC [tree: Tree, head: EvalHead, target: Type _ nullType] RETURNS [tv: TV] = {tv _ InterpreterPrivate.EvalNoProps[tree, head, target]}; EvalIf: PROC [node: Node, head: EvalHead] = { cond: Tree = node.son[1]; thenClause: Node = NARROW[node.son[2]]; elseClause: Node = NARROW[node.son[3]]; ans: BOOL _ ForceBoolean[EvalExpr[cond, head, underBOOL], head, cond]; InterpNoProps[IF ans THEN thenClause ELSE elseClause, head]; }; EvalLabelled: PROC [node: Node, head: EvalHead] = { stmt: Tree _ node.son[1]; exits: Node _ NARROW[node.son[2]]; InterpNoProps[stmt, head !GoTo => IF MatchingLabel[label, exits, head] THEN CONTINUE]; }; MatchingLabel: PROC [label: ROPE, exits: Node, head: EvalHead] RETURNS [match: BOOL] = { SELECT exits.name FROM item => {name: PPLeaves.HTIndex _ NARROW[exits.son[1]]; IF match _ label.Equal[name.name] THEN InterpNoProps[exits.son[2], head]}; list => { FOR i: NAT IN [1 .. exits.sonLimit) DO IF MatchingLabel[label, NARROW[exits.son[i]], head] THEN RETURN [TRUE]; ENDLOOP; match _ FALSE}; ENDCASE => ERROR}; EvalDo: PROC [node: Node, head: EvalHead] = { for: Node _ NARROW[node.son[1]]; test: Tree _ node.son[2]; opens: Node _ NARROW[node.son[3]]; body: Node _ NARROW[node.son[4]]; exits: Node _ NARROW[node.son[5]]; finishedExit: Node _ NARROW[node.son[6]]; LoopWork: PROC [Initial, Delta: PROC RETURNS [INT], Test: PROC RETURNS [BOOL]] = { innerHead: EvalHead _ head; FOR i: INT _ Initial[], Delta[] WHILE Test[] DO SIGNAL BackStop.SuspendBackStop[]; Process.CheckForAbort[]; SIGNAL BackStop.ResumeBackStop[]; IF opens # NIL THEN { innerHead _ NestHead[head]; AddOpens[innerHead, opens]; }; InterpNoProps[body, innerHead ! Exit => EXIT; Loop => CONTINUE; GoTo => IF MatchingLabel[label, exits, innerHead] THEN EXIT; ]; REPEAT FINISHED => InterpNoProps[finishedExit, innerHead]; ENDLOOP; innerHead _ innerHead}; IF for = NIL THEN { Dull: PROC RETURNS [i: INT] = {i _ 1}; Vanilla: PROC RETURNS [b: BOOL] = {b _ test = NIL OR ForceBoolean[EvalExpr[test, head, underBOOL], head, test]}; LoopWork[Dull, Dull, Vanilla]} ELSE SELECT for.name FROM forseq => { cv: PPLeaves.HTIndex; ctl: Tree = for.son[1]; initial: Tree = for.son[2]; delta: Tree = for.son[3]; InitialFor: PROC RETURNS [i: INT] = { EvalAssign[cv, initial, head]; i _ 0}; DeltaFor: PROC RETURNS [i: INT] = { EvalAssign[cv, delta, head]; i _ 1}; TestFor: PROC RETURNS [b: BOOL] = { b _ test = NIL OR ForceBoolean[EvalExpr[test, head, underBOOL], head, test]}; WITH ctl SELECT FROM hti: PPLeaves.HTIndex => cv _ hti; n: Node => {IF n.name # decl THEN ERROR; head _ NestHead[head]; AddDecls[head, n]; cv _ NARROW[n.son[1]]}; ENDCASE => ERROR; LoopWork[InitialFor, DeltaFor, TestFor]; }; upthru, downthru => { ctl: Tree = for.son[1]; range: Tree = for.son[2]; unknown: Tree = for.son[3]; ctv, cur: TV; rangeType: Type; int: Interval; inRange: BOOL; InitialUp: PROC RETURNS [i: INT] = { [cur, inRange] _ IntFirst[int, head, range]; IF inRange THEN AMTypes.Assign[ctv, cur]}; DeltaUp: PROC RETURNS [i: INT] = { [cur, inRange] _ IntNext[int, ctv, head, range]; IF inRange THEN AMTypes.Assign[ctv, cur]}; TestRange: PROC RETURNS [b: BOOL] = { b _ inRange AND (test = NIL OR ForceBoolean[EvalExpr[test, head, underBOOL], head, test])}; InitialDown: PROC RETURNS [i: INT] = { [cur, inRange] _ IntLast[int, head, range]; IF inRange THEN AMTypes.Assign[ctv, cur]}; DeltaDown: PROC RETURNS [i: INT] = { [cur, inRange] _ IntPrev[int, ctv, head, range]; IF inRange THEN AMTypes.Assign[ctv, cur]}; IF unknown # NIL THEN ERROR; IF ctl = NIL THEN { int _ EvalInterval[range, head, nullType]; ctv _ AMTypes.Copy[int.low]} ELSE WITH ctl SELECT FROM hti: PPLeaves.HTIndex => { ctv _ EvalExpr[hti, head]; rangeType _ AMTypes.TVType[ctv]; int _ EvalInterval[range, head, rangeType]}; n: Node => {name: Tree _ n.son[1]; type: Tree _ n.son[2]; IF n.name # decl THEN ERROR; head _ NestHead[head]; AddDecls[head, n]; ctv _ EvalExpr[name, head]; rangeType _ AMTypes.TVType[ctv]; int _ EvalInterval[range, head, rangeType]}; ENDCASE => ERROR; SELECT for.name FROM upthru => LoopWork[InitialUp, DeltaUp, TestRange]; downthru => LoopWork[InitialDown, DeltaDown, TestRange]; ENDCASE => ERROR; }; ENDCASE => ERROR; }; EvalInterval: PROC [tree: Tree, head: EvalHead, target: Type] RETURNS [int: Interval] = BEGIN node: Node _ IF ISTYPE[tree, Node] THEN NARROW[tree] ELSE NIL; intC: BOOL _ TRUE; int _ NEW [IntervalRep _ []]; IF node = NIL THEN intC _ FALSE ELSE SELECT node.name FROM intOO => int.lowClosed _ int.highClosed _ FALSE; intOC => int.lowClosed _ NOT (int.highClosed _ TRUE); intCO => int.lowClosed _ NOT (int.highClosed _ FALSE); intCC => int.lowClosed _ int.highClosed _ TRUE; ENDCASE => intC _ FALSE; IF intC THEN { lowTree: Tree _ node.son[1]; highTree: Tree _ node.son[2]; int.low _ EvalExpr[lowTree, head, target]; int.high _ EvalExpr[highTree, head, target]; } ELSE { type: Type _ ForceType[EvalExpr[tree, head, typeType], head, tree]; int.low _ AMTypes.First[type]; int.high _ AMTypes.Last[type]; int.lowClosed _ int.highClosed _ TRUE; }; END; IntFirst: PROC [int: Interval, head: EvalHead, parent: Tree] RETURNS [first: TV, inRange: BOOL] = BEGIN rtv: TV; first _ int.low; IF NOT int.lowClosed THEN first _ AMTypes.Next[first]; IF first = NIL THEN RETURN [NIL, FALSE]; rtv _ EvalBinop[first, int.high, IF int.highClosed THEN relLE ELSE relL, head, underBOOL, parent]; inRange _ SELECT rtv FROM true => TRUE, false => FALSE, ENDCASE => ERROR; END; IntNext: PROC [int: Interval, cur: TV, head: EvalHead, parent: Tree] RETURNS [next: TV, inRange: BOOL] = BEGIN rtv: TV; next _ AMTypes.Next[cur]; IF next = NIL THEN RETURN [NIL, FALSE]; rtv _ EvalBinop[next, int.high, IF int.highClosed THEN relLE ELSE relL, head, underBOOL, parent]; inRange _ SELECT rtv FROM true => TRUE, false => FALSE, ENDCASE => ERROR; END; IntLast: PROC [int: Interval, head: EvalHead, parent: Tree] RETURNS [last: TV, inRange: BOOL] = BEGIN rtv: TV; last _ int.high; IF NOT int.highClosed THEN last _ Prev[last, head, parent]; IF last = NIL THEN RETURN [NIL, FALSE]; rtv _ EvalBinop[last, int.low, IF int.lowClosed THEN relGE ELSE relG, head, underBOOL, parent]; inRange _ SELECT rtv FROM true => TRUE, false => FALSE, ENDCASE => ERROR; END; IntPrev: PROC [int: Interval, cur: TV, head: EvalHead, parent: Tree] RETURNS [prev: TV, inRange: BOOL] = BEGIN rtv: TV; prev _ Prev[cur, head, parent]; IF prev = NIL THEN RETURN [NIL, FALSE]; rtv _ EvalBinop[prev, int.low, IF int.lowClosed THEN relGE ELSE relG, head, underBOOL, parent]; inRange _ SELECT rtv FROM true => TRUE, false => FALSE, ENDCASE => ERROR; END; Prev: PROC [tv: TV, head: EvalHead, parent: Tree] RETURNS [prev: TV] = {IF AMTypes.TVEqual[tv, AMTypes.First[AMTypes.TVType[tv]]] THEN RETURN [NIL]; prev _ EvalBinop[tv, one, minus, head, nullType, parent]}; true, false, one: TV _ NIL; EvalBinop: PROC [lval, rval: TV, kind: PPTree.NodeName, head: EvalHead, target: Type, parent: Tree] RETURNS [rtn: TV _ NIL] = { op: PPTree.NodeName _ kind; ltype, rtype, ttype, altype, artype: Type; lclass, rclass, alclass, arclass, targClass: AMTypes.Class; rtnBit: BOOL; ttype _ AMTypes.TVType[lval]; ltype _ AMTypes.UnderType[ttype]; lclass _ AMTypes.TypeClass[ltype]; IF target = nullType THEN target _ ttype; rtype _ AMTypes.UnderType[AMTypes.TVType[rval]]; rclass _ AMTypes.TypeClass[rtype]; targClass _ AMTypes.TypeClass[AMTypes.GroundStar[target]]; SELECT kind FROM relE, relN => SELECT lclass FROM subrange, cardinal, integer, character, longInteger, longCardinal, real, unspecified => -- these values must be arithmetic op _ minus ENDCASE => { eq: BOOL _ AMTypes.TVEqual[lval, rval]; IF kind = relN THEN eq _ NOT eq; RETURN [IF eq THEN true ELSE false]; }; relL, relGE, relG, relLE => op _ minus ENDCASE; lval _ ForceArithmetic[lval, head, parent]; altype _ AMTypes.UnderType[AMTypes.TVType[lval]]; alclass _ AMTypes.TypeClass[altype]; rval _ ForceArithmetic[rval, head, parent]; artype _ AMTypes.UnderType[AMTypes.TVType[rval]]; arclass _ AMTypes.TypeClass[artype]; IF alclass = real OR arclass = real THEN TRUSTED { -- raise conciousness to the real level lreal: REAL _ AMBridge.TVToReal[lval]; rreal: REAL _ AMBridge.TVToReal[rval]; IF lclass # real THEN lreal _ AMBridge.TVToLI[lval]; IF rclass # real THEN rreal _ AMBridge.TVToLI[rval]; SELECT op FROM plus => lreal _ lreal + rreal; minus => lreal _ lreal - rreal; times => lreal _ lreal * rreal; div => lreal _ lreal / rreal; mod => lreal _ Real.FRem[lreal, rreal]; min => lreal _ MIN[lreal, rreal]; max => lreal _ MAX[lreal, rreal] ENDCASE => ERROR; SELECT kind FROM relE => rtnBit _ lreal = 0.0; relN => rtnBit _ lreal # 0.0; relL => rtnBit _ lreal < 0.0; relGE => rtnBit _ lreal >= 0.0; relG => rtnBit _ lreal > 0.0; relLE => rtnBit _ lreal <= 0.0; ENDCASE => IF targClass = enumerated THEN BBUrpEval.UrpFatal[head, parent, "can't do REAL arithmatic with enumerated values"] ELSE RETURN [InterpreterPrivate.NewReal[lreal]]; IF rtnBit THEN RETURN [true] ELSE RETURN [false]; }; TRUSTED { lint: INT _ AMBridge.TVToLI[lval]; rint: INT _ AMBridge.TVToLI[rval]; SELECT op FROM plus => lint _ lint + rint; minus => lint _ lint - rint; times => lint _ lint * rint; div => lint _ lint / rint; mod => lint _ lint MOD rint; min => lint _ MIN[lint, rint]; max => lint _ MAX[lint, rint] ENDCASE => ERROR; SELECT kind FROM relE => rtnBit _ lint = 0; relN => rtnBit _ lint # 0; relL => rtnBit _ lint < 0; relGE => rtnBit _ lint >= 0; relG => rtnBit _ lint > 0; relLE => rtnBit _ lint <= 0; ENDCASE => IF targClass = enumerated THEN {new: TV _ AMTypes.New[target]; AMBridge.SetTVFromLC[new, LOOPHOLE[lint]]; RETURN [new]} ELSE RETURN [InterpreterPrivate.NewInt[lint]]; IF rtnBit THEN RETURN [true] ELSE RETURN [false]; } }; ForceArithmetic: PROC [val: TV, head: EvalHead, parent: Tree] RETURNS [rtn: TV] = TRUSTED { type: Type; ground: Type; class: AMTypes.Class; rtn _ StripSingleComponentRecord[val]; type _ AMTypes.TVType[rtn]; ground _ AMTypes.GroundStar[type]; class _ AMTypes.TypeClass[ground]; SELECT class FROM real => IF type # ground THEN rtn _ InterpreterPrivate.NewReal[AMBridge.TVToReal[rtn]]; cardinal, character, unspecified => rtn _ InterpreterPrivate.NewInt[AMBridge.TVToCardinal[rtn]]; integer => rtn _ InterpreterPrivate.NewInt[AMBridge.TVToInteger[rtn]]; longCardinal => rtn _ InterpreterPrivate.NewInt[LOOPHOLE[AMBridge.TVToLC[rtn], INT]]; longInteger => IF type # ground THEN rtn _ InterpreterPrivate.NewInt[AMBridge.TVToLI[rtn]]; enumerated => rtn _ InterpreterPrivate.NewInt[AMBridge.TVToCardinal[rtn]]; ENDCASE => BBUrpEval.UrpFatal[head, parent, "not a number"]; }; EvalAssign: PROC [name: PPLeaves.HTIndex, valueT: Tree, head: EvalHead] = { n: Node _ NEW [PPTree.Node[assTemp.sonLimit]]; n.name _ assTemp.name; n.attr _ assTemp.attr; n.info _ assTemp.info; n.son[1] _ name; n.son[2] _ valueT; IF assTemp.sonLimit # 3 THEN ERROR; [] _ InterpNoProps[n, head]}; assTemp: Node _ NARROW[First[assign, ParseBlock["{x _ 1}", IO.ROS[]]]]; EvalBody: PROC [node: Node, head: EvalHead, nest: BOOL] = { opens: Node _ NARROW[node.son[1]]; decls: Node _ NARROW[node.son[2]]; stmts: Node _ NARROW[node.son[3]]; IF decls # NIL OR opens # NIL THEN { IF nest THEN head _ NestHead[head]; IF opens # NIL THEN AddOpens[head, opens]; IF decls # NIL THEN AddDecls[head, decls]; }; InterpNoProps[stmts, head]; }; EvalBlock: PROC [node: Node, head: EvalHead, nest: BOOL] = { decls: Node _ NARROW[node.son[1]]; stmts: Node _ NARROW[node.son[2]]; IF decls # NIL THEN { IF nest THEN head _ NestHead[head]; AddDecls[head, decls]}; InterpNoProps[stmts, head]; }; EvalOpen: PROC [node: Node, head: EvalHead, nest: BOOL] = { opens: Node _ NARROW[node.son[1]]; stmts: Node _ NARROW[node.son[2]]; IF opens # NIL THEN { IF nest THEN head _ NestHead[head]; AddOpens[head, opens]; }; InterpNoProps[stmts, head]; }; NestHead: PUBLIC PROC [outer: EvalHead, st: SymbolTable _ NIL] RETURNS [inner: EvalHead] = BEGIN found: BOOL; sttv, sttv2: TV; IF st = NIL THEN st _ outer.specials; inner _ NEW [InterpreterOps.EvalHeadRep _ outer^]; inner.specials _ CopySymbolTable[st]; [found, sttv] _ inner.specials.Fetch["&EvalQuoteSymTab"]; IF found THEN { eqst, eqst2: SymbolTable; TRUSTED {eqst _ NarrowToSymbolTable[AMBridge.RefFromTV[sttv]]}; eqst2 _ CopySymbolTable[eqst]; TRUSTED {sttv2 _ AMBridge.TVForReferent[eqst2]}; [] _ inner.specials.Store["&EvalQuoteSymTab", sttv2]}; END; CopySymbolTable: PROC [old: SymbolTable] RETURNS [new: SymbolTable] = BEGIN ToNew: PROC [key: SymTab.Key, val: SymTab.Val] RETURNS [quit: BOOL] --SymTab.EachPairAction-- = {[] _ SymTab.Store[new, key, val]; quit _ FALSE}; new _ SymTab.Create[]; [] _ SymTab.Pairs[old, ToNew]; END; AddDecls: PROC [head: EvalHead, decls: Node] = { AddDecl: PROC [namesT, typeT, valueT: Tree] = { IF typeT # NIL AND valueT # NIL AND ISTYPE[typeT, Node] AND ISTYPE[valueT, Node] THEN { PerProcName: PROC [nameT: Tree] = { AddProcDecl[NARROW[nameT], typeN, bodyN, head]; nameT _ nameT}; typeN: Node = NARROW[typeT]; bodyN: Node; IF typeN.name = procTC THEN { bodyN _ NARROW[valueT]; PPTreeOps.ScanList[namesT, PerProcName]; namesT _ namesT; RETURN}; namesT _ namesT; }; --otherwise--{ type: Type _ ForceType[EvalExpr[typeT, head, typeType], head, typeT]; PerName: PROC [nameT: Tree] = { name: PPLeaves.HTIndex = NARROW[nameT]; val: TV _ AMTypes.New[type]; IF valueT # NIL THEN AMTypes.Assign[val, EvalExpr[valueT, head, type]]; [] _ head.specials.Store[name.name, val]; }; PerProc: PROC [nameT: Tree] = { name: PPLeaves.HTIndex = NARROW[nameT]; AddTypedProc[name, type, NARROW[valueT], head]; }; PPTreeOps.ScanList[ namesT, SELECT AMTypes.UnderClass[type] FROM procedure => PerProc, ENDCASE => PerName ]; } }; AddTypeDecl: PROC [namesT, typeT: Tree] = { PerName: PROC [nameT: Tree] = { name: PPLeaves.HTIndex = NARROW[nameT]; [] _ head.specials.Store[name.name, val]; }; type: Type _ ForceType[EvalExpr[typeT, head, typeType], head, typeT]; val: TV; TRUSTED {val _ AMBridge.TVForType[type]}; PPTreeOps.ScanList[namesT, PerName]; }; SELECT decls.name FROM decl => AddDecl[decls.son[1], decls.son[2], decls.son[3]]; typedecl => AddTypeDecl[decls.son[1], decls.son[2]]; list => FOR i: NAT IN [1 .. decls.sonLimit) DO AddDecls[head, NARROW[decls.son[i]]]; ENDLOOP; ENDCASE => ERROR; head _ head}; AddProcDecl: PROC [nameT: PPLeaves.HTIndex, procTypeC, body: Node, head: EvalHead] = { procArgs: Node _ NARROW[procTypeC.son[1]]; procRets: Node _ NARROW[procTypeC.son[2]]; l: Lambda _ NEW[LambdaRep _ [ name: nameT.name, args: DigestFields[procArgs, TRUE, FALSE, head], rets: DigestFields[procRets, TRUE, FALSE, head], body: body, head: head]]; ds: DummyStuff = AllocConsdProc[l]; ltv: TV; IF ds # NIL THEN { procType: Type = AMTypes.TVType[ltv _ ds.asTV]; l.argsType _ AMTypes.Domain[procType]; l.retsType _ AMTypes.Range[procType]; ds.asLambda _ l; EvalQuote.Register[l.name, NIL, head.specials, NIL]; [] _ head.specials.Store[l.name, ltv]; } ELSE { TRUSTED {ltv _ AMBridge.TVForReferent[NEW [Lambda _ l]]}; IF l.rets.length > 1 THEN BBUrpEval.UrpFatal[head, procTypeC, "Can't handle more than one return"]; EvalQuote.Register[l.name, EvalProcedure, head.specials, l]; IF nameToo THEN [] _ head.specials.Store[l.name, ltv]; }; ltv _ ltv; }; nameToo: BOOL _ TRUE; AddTypedProc: PROC [nameT: PPLeaves.HTIndex, procType: Type, body: Node, head: EvalHead] = { procArgs: Type = AMTypes.Domain[procType]; procRets: Type = AMTypes.Range[procType]; l: Lambda = NEW[LambdaRep _ [ name: nameT.name, args: FieldsFromType[procArgs], rets: FieldsFromType[procRets], argsType: procArgs, retsType: procRets, body: body, head: head]]; ds: DummyStuff = AllocProc[procType]; ltv: TV; IF ds # NIL THEN { ltv _ ds.asTV; ds.asLambda _ l; EvalQuote.Register[l.name, NIL, head.specials, NIL]; [] _ head.specials.Store[l.name, ltv]; } ELSE { TRUSTED {ltv _ AMBridge.TVForReferent[NEW [Lambda _ l]]}; EvalQuote.Register[l.name, EvalProcedure, head.specials, l]; IF nameToo THEN [] _ head.specials.Store[l.name, ltv]; }; ltv _ ltv; }; AddOpens: PROC [head: EvalHead, opens: Node] = { PerOpen: PROC [t: Tree] --PPTree.Scan-- = { open: Node = NARROW[t]; nameT: PPLeaves.HTIndex = NARROW[open.son[1]]; valueT: Tree = open.son[2]; IF open.name # item THEN ERROR; IF nameT # NIL THEN AddSimpleOpen[head, nameT.name, valueT, dontSelect] ELSE AddComplexOpen[head, valueT]; }; PPTreeOps.ScanList[opens, PerOpen]; }; AddComplexOpen: PROC [head: EvalHead, recordT: Tree] = { recordTV: TV _ EvalExpr[recordT, head]; recordType: Type _ DeRefToRecord[head, recordT, recordTV].type; FOR i: INT IN [1 .. AMTypes.NComponents[recordType]] DO name: ROPE = AMTypes.IndexToName[recordType, i]; IF name.Length[] = 0 THEN BBUrpEval.UrpFatal[head, recordT, "Can't handle anonymouse field"]; AddSimpleOpen[head, name, recordT, i] ENDLOOP; head _ head; }; DeRefToRecord: PROC [head: EvalHead, recordT: Tree, ur: TV] RETURNS [tv: TV, type: Type] = { tv _ ur; DO class: AMTypes.Class = AMTypes.TypeClass[type _ AMTypes.UnderType[AMTypes.TVType[tv]]]; SELECT class FROM record, structure => EXIT; definition => ERROR; ref, pointer, longPointer => tv _ AMTypes.Referent[tv]; globalFrame => tv _ AMTypes.Globals[tv]; ENDCASE => BBUrpEval.UrpFatal[head, recordT, "Not a record TYPE"]; ENDLOOP; head _ head; }; dontSelect: INTEGER = FIRST[INTEGER]; AddSimpleOpen: PROC [head: EvalHead, name: ROPE, recordT: Tree, i: INTEGER] = { EvalQuote.RegisterNameProc[ name: name, symTab: head.specials, proc: OpenName, data: NEW [OpenRep _ [head, recordT, i]] ]; }; OpenRep: TYPE = RECORD [head: EvalHead, tree: Tree, i: INTEGER]; OpenName: PROC [head: EvalHead, nameAsRope: ROPE, nameAsTree: Tree, target: Type _ nullType, data: REF _ NIL] RETURNS [value: TV] --EvalQuote.NameProc-- = { ro: REF OpenRep = NARROW[data]; ur: TV _ EvalExpr[ro.tree, ro.head]; IF ro.i = dontSelect THEN RETURN [ur]; value _ AMTypes.IndexToTV[DeRefToRecord[ro.head, ro.tree, ur].tv, ro.i]; }; ParseModule: PUBLIC PROC [asRope: ROPE, errout: IO.STREAM] RETURNS [asTree: Tree] = { complete: BOOL; nErrors: CARDINAL; PPTreeOps.Initialize[]; TRUSTED {[complete, , nErrors] _ PPP1.Parse[ asRope, LOOPHOLE[PrincOpsUtils.Codebase[LOOPHOLE[CBinary.MesaTab, PrincOps.GlobalFrameHandle]]], errout ]}; asTree _ IF complete AND nErrors = 0 THEN PPTreeOps.PopTree[] ELSE PPTree.Null; PPTreeOps.Finalize[]; }; ParseBlock: PUBLIC PROC [asRope: ROPE, errout: IO.STREAM] RETURNS [asTree: Tree] = { asRope _ Rope.Cat["Block: PROGRAM = ", asRope, "."]; asTree _ ParseModule[asRope: asRope, errout: errout]; asTree _ First[body, asTree]; }; StripSingleComponentRecord: PROC [tv: TV, max: NAT _ 100] RETURNS [rtn: TV] = TRUSTED { rtn _ tv; THROUGH [0..max) DO under: Type = AMTypes.UnderType[AMTypes.TVType[rtn]]; class: AMTypes.Class _ AMTypes.UnderClass[under]; IF (class # record AND class # structure) OR (AMTypes.NComponents[under] # 1) THEN EXIT; rtn _ AMTypes.IndexToTV[rtn, 1]; ENDLOOP; }; underBOOL: Type _ AMTypes.UnderType[CODE[BOOL]]; trueCard: CARDINAL _ LOOPHOLE[TRUE, CARDINAL]; falseCard: CARDINAL _ LOOPHOLE[FALSE, CARDINAL]; ForceBoolean: PROC [tv: TV, head: EvalHead, parent: Tree] RETURNS [BOOL] = TRUSTED { rtn: TV _ tv; DO rtn _ StripSingleComponentRecord[rtn]; IF AMTypes.UnderType[AMTypes.TVType[rtn]] = underBOOL THEN { card: CARDINAL _ AMBridge.TVToCardinal[rtn]; IF card = trueCard THEN RETURN [TRUE]; IF card = falseCard THEN RETURN [FALSE]}; rtn _ BBUrpEval.UrpWrongType[head, parent, rtn, underBOOL, "not boolean"] ENDLOOP }; underType: Type _ AMTypes.UnderType[CODE[Type]]; ForceType: PUBLIC PROC [tv: TV, head: EvalHead, parent: Tree] RETURNS [Type] = TRUSTED { rtn: TV _ tv; DO ut: Type = AMTypes.UnderType[AMTypes.TVType[rtn]]; IF ut = underType THEN RETURN [AMTypes.TVToType[rtn]]; IF AMTypes.TypeClass[ut] = type THEN RETURN [AMTypes.TVToType[rtn]]; rtn _ BBUrpEval.UrpWrongType[head, parent, rtn, underType, "not Type"] ENDLOOP }; AddMissingTypes: PROC = TRUSTED { st: SymTab.Ref _ InterpreterPrivate.GetGlobalSymTab[]; IF NOT st.Fetch["REAL"].found THEN {IF NOT st.Store["REAL", AMBridge.TVForType[CODE[REAL]]] THEN ERROR}; IF NOT st.Fetch["NAT"].found THEN {IF NOT st.Store["NAT", AMBridge.TVForType[CODE[NAT]]] THEN ERROR}; IF NOT st.Fetch["UNWIND"].found THEN {IF NOT st.Store["UNWIND", AMBridge.TVForSignal[UNWIND]] THEN ERROR}; IF NOT st.Fetch["ABORTED"].found THEN {IF NOT st.Store["ABORTED", AMBridge.TVForSignal[ABORTED]] THEN ERROR}; }; nodeNames: ARRAY PPTree.NodeName OF ROPE; Start: PROC = { rnn: REF PPTree.NodeName _ NEW [PPTree.NodeName]; tvnn: TV; TRUSTED {tvnn _ AMBridge.TVForReferent[rnn]}; FOR nn: PPTree.NodeName IN PPTree.NodeName DO rnn^ _ nn; nodeNames[nn] _ AMTypes.TVToName[tvnn]; ENDLOOP; TRUSTED { typeType _ AMTypes.TVType[AMBridge.TVForType[CODE[BOOL]]]; true _ AMBridge.TVForReferent[NEW[BOOL _ TRUE]]; false _ AMBridge.TVForReferent[NEW[BOOL _ FALSE]]; one _ AMBridge.TVForReferent[NEW[NAT _ 1]]; }; IF AMTypes.TypeClass[typeType] # type THEN ERROR; Commander.Register[ key: "{", proc: StatementCommand, doc: "a statement evaluation command", interpreted: FALSE]; AddMissingTypes[]; }; Start[]; END. ^StatementCommands.Mesa Last Edited by: Spreitzer, May 10, 1986 3:56:39 pm PDT don't bother: SIGNAL BackStop.ResumeBackStop[] At this point the values must be arithmetic. ForceArithmetic forces the given value to be arithmetic; the result is a TV with class = real or class = longInteger. Try to get the right stuff. Try to get the right stuff. ส$– "cedar" style˜code™K™6—K˜Kšฯk œ^œAœภ˜์K˜šะbxœœ˜ Kšœ^œ4œš˜ทKšœ4˜;—K˜Kšœœ3˜=K˜Kšœ œ˜K˜Jšœœœ˜(Kšœ œ˜J˜Kšœœœœ˜Kšœœœœ˜Kš œœœœœ˜?Kšœœœœ˜-Kš œœœœœ˜?Kšœœœœ˜-Kš œœœ œœ˜(Kšœœœ'œ˜FK˜Kšœœœœ˜2šœœœ˜K˜Kšœ œ˜Kšœ˜K˜—K˜Kšœ&œ˜*K˜Kšœœ ˜Kšœœ˜$K˜šฯnœœœ œ&˜QKšœ œœ ˜3Kšœœ˜K˜Kšœ)˜0Kšœ ˜ K˜&šœœœ)˜8Kšœ˜Kšœœ'˜1K˜K˜ Kšœ˜Kšœ/œœ˜;K˜#K˜šœ˜$Kšœ œ˜Kšœœ˜—šœ˜ šœœ˜Kšœ˜K˜ —K˜—Kšœ˜Kšœœœœ$˜PKšœœ˜(Kšœ˜—K˜—K˜šŸœœœ˜JKšœœœœœ:œœœ˜‚K˜—K˜šŸœœ œ˜JKšœœœœœ7œ6œœœ˜ธK˜—K˜šŸ œœ$œ œ˜Nšœœœ ˜6K˜ Kšœ5˜5Kšœœ˜—Kšœœœœ˜,šœœœ˜%Kšœœ(˜3Kšœœ˜Kšœœœœœœœ˜\Kš œœSœœœ˜mKšœ˜—Kšœ œ˜K˜—K˜K˜8K˜šŸ œœœ˜=Kšœ2˜2Kš œœœœœ˜šœœœ˜KšœFœ˜LK˜—Kš œœœœœ˜)K˜K˜#Kš œœœ œœœ˜EK˜—K˜šŸœœ œ˜=Kšœ0˜0Kš œœœœœ˜šœœœ˜KšœFœ˜LK˜—Kš œœœœœ˜)K˜K˜#Kš œœœ œœœ˜EK˜—K˜š Ÿœœœ œœ˜CKšœœœœ ˜@K˜—K˜š Ÿœœœœœœ˜LKšœœ˜Kšœ˜—K˜Kšœ?œ˜]K˜šŸœœœ œœœœฯcœ˜yKšœ œ"˜3Kšœœ˜ Kšœ œ˜Kšœ œ4˜ZKšœ˜Kšœ˜Kšœ œ&˜3Kšœ œœ˜Kšœ œ0˜Všœ˜ Kšœœ6˜Bšœ˜Kšœ˜šœ ˜KšœœE˜Q—Kšœ˜——KšœG˜Nšœ œœ˜Kšœ˜KšœG˜GKšœ˜—Kšœ/˜/K˜=šœ œœ˜Kšœ6˜6K˜Kšœ˜—šœ˜ Kšœ;˜;Kšœœ4˜@K˜—K˜—K˜šŸœœœœœœDœ œ˜ฦšŸœœ˜Kšœ6˜6šœ˜Kšœ˜šœ!˜!Kšœ˜Kšœ˜Kšœ-˜-Kšœ˜—Kšœ˜ Kšœ5œ˜@—K˜—Kš œ œœœœ˜"Kšœ œœœ7˜TKšœ œœ˜.Kšœ*˜*Kšœ œ˜(Kšœ˜—K˜Kšœœœœ˜/š œ œœ%œ œœ˜oKšœ˜!K˜—K˜šŸœœ!œ˜CKš œœœœœ˜šœœ˜˜ Kšœ œœ˜šœœœ˜"K˜Kšœœœœ˜Kšœ˜ ——Kšœ˜—Kšœœ˜ —K˜š Ÿ œœ œœœ% #œ˜xKšœœ˜%—K˜š Ÿœœœ&œœ˜IKšŸœœœ˜:KšœHœ˜MKšœ8œ ˜EKšœ˜—K˜š Ÿ œœœ$œœ˜Nš œœœœœ˜(˜šœ ˜šœœœœ˜,Kšœ!˜!Kšœ˜—Kšœ@˜@Kšœ2˜2K˜#K˜%K˜K˜K˜"K˜!Kšœ!˜!Kšœœ˜šœ ˜ Kšœ˜"Kšœ˜Kšœ.™.K˜—Kšœœ˜šœ ˜ Kšœœ˜-Kšœ˜—Kšœ œ˜%Kšœ œ˜#Kšœ œ˜)Kšœœ˜ šœ ˜ KšŸ œœœ˜=Kšœœ ˜-Kšœ˜—K˜#Kšœœœ˜—š˜KšœX˜[—K˜—Kšœ˜%—Kšœ˜—K˜š Ÿœœœ7œœ˜^Kšœ:˜:—K˜šŸœœ!˜-K˜Kšœœ˜'Kšœœ˜'Kšœœ=˜FKšœœœ œ˜Kšœœœ˜Kšœœ˜Kšœœœ˜šœœ ˜Kšœ*œ˜0Kšœœœ˜5Kšœœœ˜6Kšœ*œ˜/Kšœ œ˜—šœ˜šœ˜K˜K˜K˜*K˜,K˜—šœ˜KšœC˜CK˜K˜Kšœ!œ˜&K˜——Kšœ˜—K˜š Ÿœœ/œ œ œ˜aKš˜Kšœœ˜K˜Kšœœœ˜6Kš œ œœœœœ˜(Kšœ!œœœ ˜bšœ œ˜Kšœœ˜ Kšœ œ˜Kšœœ˜—Kšœ˜—K˜š Ÿœœœ œœ œ˜hKš˜Kšœœ˜K˜Kš œœœœœœ˜'Kšœ œœœ ˜ašœ œ˜Kšœœ˜ Kšœ œ˜Kšœœ˜—Kšœ˜—K˜š Ÿœœ/œœ œ˜_Kš˜Kšœœ˜Kšœ˜Kšœœœ!˜;Kš œœœœœœ˜'Kšœœœœ ˜_šœ œ˜Kšœœ˜ Kšœ œ˜Kšœœ˜—Kšœ˜—K˜š Ÿœœœ œœ œ˜hKš˜Kšœœ˜Kšœ˜Kš œœœœœœ˜'Kšœœœœ ˜_šœ œ˜Kšœœ˜ Kšœ œ˜Kšœœ˜—Kšœ˜—K˜š Ÿœœœ œœ˜FKš œœ8œœœ˜MK˜:—K˜Jšœœœ˜J˜š Ÿ œœœEœœœ˜K˜K˜*K˜;Kšœœ˜ K˜K˜!K˜"Kšœœ˜)K˜0K˜"K˜:šœ˜˜ šœ˜K˜Bšœ "˜7K˜ —šœ˜ Kšœœ˜'Kšœ œœ˜ Kšœœœœ˜$Kšœ˜———K˜&Kšœ˜ K˜—Kšœ,™,K˜K˜+K˜1K˜$K˜+K˜1K˜$šœœœœ˜2Kš '˜'Kšœœ˜&Kšœœ˜&Kšœœ˜4Kšœœ˜4šœ˜K˜K˜K˜K˜K˜'Kšœœ˜!Kšœœ˜ Kšœœ˜—šœ˜Kšœœ ˜Kšœœ ˜Kšœœ ˜Kšœœ˜Kšœœ ˜Kšœœ˜Kš œœœUœœ%˜ฎ—Kš œœœœœ ˜1Kšœ˜—šœ˜ Kšœœ˜"Kšœœ˜"šœ˜K˜K˜K˜K˜Kšœœ˜Kšœœ ˜Kšœœ ˜Kšœœ˜—šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜šœœ˜$šœœ˜$Kšœœ˜*Kšœ˜ —Kšœœ#˜.——Kš œœœœœ ˜1Kšœ˜—K˜—J˜š Ÿœœœœœœ˜[šœu™uK˜ K˜ K˜Kšœ&˜&K˜K˜"K˜"šœ˜˜Kšœœ:˜O—˜#K˜<—˜ K˜;—˜Kšœ œœ˜E—˜Kšœœ7˜L—K˜JKšœ5˜<——K˜—J˜šŸ œœ;˜KKšœ œ!˜.K˜K˜K˜Kšœ˜Kšœ˜Kšœœœ˜#Kšœ˜—K˜Kšœœ%œœ˜GK˜šŸœœ$œ˜;Kšœœ˜"Kšœœ˜"Kšœœ˜"š œ œœ œœ˜$Kšœœ˜#Kšœ œœ˜*Kšœ œœ˜*K˜—Kšœ˜K˜—K˜šŸ œœ$œ˜