<> <> <> DIRECTORY RussellRuntime USING [ RTValue, RTTuple, ConsRTNode, BindingRTNode, RTCodeBody, RTClosure, ClosureRTNode, RTLocation] ; RussellRuntimeImpl: CEDAR PROGRAM EXPORTS RussellRuntime = BEGIN OPEN RussellRuntime ; <> RTError: PUBLIC ERROR[ec: ATOM] = CODE; <> MkTuple: PUBLIC PROCEDURE [name: ATOM, value: RTValue] RETURNS [RTTuple] = BEGIN RETURN[ NEW[BindingRTNode _ [name~name, value~value]]] END; ConcatTuple: PUBLIC PROCEDURE [tuple1,tuple2: RTValue] RETURNS [RTTuple] = BEGIN RETURN[ NEW[ConsRTNode _ [leftPart~tuple1,rightPart~tuple2]]] END; SelectFromTuple: PUBLIC PROCEDURE [tuple: RTValue, name: ATOM] RETURNS [RTValue] = BEGIN answer: RTValue _ NIL; DoSelection: PROCEDURE [t: RTTuple] RETURNS[ BOOL ] <> <> = BEGIN p: RTTuple _ t; nextp: RTTuple _ NIL; DO IF p = NIL THEN BEGIN IF nextp = NIL THEN RETURN[ FALSE ]; p _ nextp; nextp _ NIL END ; <> WITH p SELECT FROM pb: REF BindingRTNode => BEGIN IF pb.name = name THEN BEGIN answer _ pb.value; RETURN[ TRUE ] END ELSE BEGIN p _ NIL END END ; pc: REF ConsRTNode => SELECT TRUE FROM nextp = NIL => BEGIN p _ pc.leftPart; nextp _ pc.rightPart END ; pc.rightPart = NIL => p _ pc.leftPart ; pc.leftPart = NIL => p _ pc.rightPart ; ENDCASE => BEGIN IF DoSelection[pc.leftPart] THEN RETURN[ TRUE ] ; p _ pc.rightPart END ; ENDCASE => RETURN[ FALSE ] ; ENDLOOP END ; -- DoSelection IF DoSelection[ NARROW[tuple] ] THEN RETURN[ answer ] ELSE ERROR RTError[ec~$badTuple] ; END ; -- SelectFromTuple QueryTuple: PUBLIC PROCEDURE [tuple: RTValue, name: ATOM] RETURNS [BOOL] = BEGIN DoQuery: PROCEDURE [t: RTTuple] RETURNS[ BOOL ] <> <> = BEGIN p: RTTuple _ t; nextp: RTTuple _ NIL; DO IF p = NIL THEN BEGIN IF nextp = NIL THEN RETURN[ FALSE ]; p _ nextp; nextp _ NIL END ; <> WITH p SELECT FROM pb: REF BindingRTNode => BEGIN IF pb.name = name THEN RETURN[ TRUE ] ELSE p _ NIL END ; pc: REF ConsRTNode => SELECT TRUE FROM nextp = NIL => BEGIN p _ pc.leftPart; nextp _ pc.rightPart END ; pc.rightPart = NIL => p _ pc.leftPart ; pc.leftPart = NIL => p _ pc.rightPart ; ENDCASE => BEGIN IF DoQuery[pc.leftPart] THEN RETURN[ TRUE ] ; p _ pc.rightPart END ; ENDCASE => RETURN[ FALSE ] ; ENDLOOP END ; -- DoQuery RETURN[ DoQuery[ NARROW[tuple] ] ] END ; -- QueryTuple <> MkClosure: PUBLIC PROCEDURE [ep: RTValue, ip: REF ANY, cb: RTCodeBody] RETURNS [RTClosure] = BEGIN RETURN[ NEW[ ClosureRTNode _ [ep~NARROW[ep], ip~ip, cb~cb] ]] END ; -- MkClosure ApplyClosure: PUBLIC PROCEDURE [closure: RTValue, arg: RTValue ] RETURNS [RTValue] = BEGIN WITH closure SELECT FROM c: RTClosure => RETURN[ c.cb[ env~c.ep, arg~arg, ip~c.ip ] ] ; ENDCASE => ERROR RTError[ec~$badClosure] ; END ; -- ApplyClosure <> PrependValue: PUBLIC PROCEDURE [tuple: RTTuple, name: ATOM, value: RTValue] RETURNS[RTTuple] = BEGIN RETURN[ ConcatTuple[ MkTuple[name~name,value~value], tuple ]] END ; -- PrependValue PrependProc: PUBLIC PROCEDURE [tuple: RTTuple, name: ATOM, body: RTCodeBody] RETURNS[RTTuple] = BEGIN RETURN[ ConcatTuple[ MkTuple[name~name, value~MkClosure[ep~NIL, ip~NIL, cb~body]], tuple ] ] END ; -- PrependProc <> ValueOf: PUBLIC PROCEDURE [location: RTValue] RETURNS [RTValue] = BEGIN WITH location SELECT FROM loc: RTLocation => RETURN[ loc^ ] ; ENDCASE => ERROR RTError[ec~$badLocation] ; END ; -- ValueOf Assign: PUBLIC PROCEDURE [location: RTValue, value: RTValue] RETURNS [RTValue] = BEGIN WITH location SELECT FROM loc: RTLocation => RETURN[ (loc^ _ value) ] ; ENDCASE => ERROR RTError[ec~$badLocation] ; END ; -- Assign New: PUBLIC PROCEDURE [] RETURNS [RTLocation] = BEGIN RETURN[ NEW[ RTValue _ NIL ] ] END ; -- New END .