@@ -232,16 +232,14 @@ impl InstructionBuilder {
232232 p1,
233233 p2,
234234 p3,
235- } => {
236- lvar ( p2) ;
237- lvar ( p3) ;
238- Control {
239- control,
240- target : lvar ( target) ,
241- p1 : lvar ( p1) ,
242- }
243- . into ( )
235+ } => Control {
236+ control,
237+ target : lvar ( target) ,
238+ p1 : lvar ( p1) ,
239+ p2 : lvar ( p2) ,
240+ p3 : lvar ( p3) ,
244241 }
242+ . into ( ) ,
245243 ast:: Instruction :: Sensor {
246244 result,
247245 target,
@@ -383,13 +381,13 @@ impl Read {
383381}
384382
385383impl SimpleInstructionTrait for Read {
386- fn execute ( & self , state : & mut ProcessorState , _ : & LogicVM ) {
384+ fn execute ( & self , state : & mut ProcessorState , vm : & LogicVM ) {
387385 let address = self . address . get ( state) ;
388386 let target = self . target . get ( state) ;
389387
390388 match target. obj ( ) {
391389 Some ( LObject :: Building ( building) ) => borrow_data ! (
392- building. data. clone ( ) ,
390+ mut building. data,
393391 state: target_state => {
394392 // read variable with name, returning null for constants and undefined
395393 // or no-op if the address is not a string
@@ -427,8 +425,14 @@ impl SimpleInstructionTrait for Read {
427425 . setnum( state, Self :: read_slice( message. as_slice( ) , & address) ) ;
428426 }
429427
428+ BuildingData :: Custom ( custom) => {
429+ if let Some ( value) = custom. read( state, vm, address. into_owned( ) ) {
430+ self . result. set( state, value) ;
431+ }
432+ }
433+
430434 // no-op if the target doesn't support reading
431- _ => { } ,
435+ _ => { }
432436 } ,
433437 ) ,
434438
@@ -451,14 +455,14 @@ pub struct Write {
451455 pub address : LVar ,
452456}
453457
454- impl SimpleInstructionTrait for Write {
455- fn execute ( & self , state : & mut ProcessorState , _ : & LogicVM ) {
458+ impl InstructionTrait for Write {
459+ fn execute ( & self , state : & mut ProcessorState , vm : & LogicVM ) -> InstructionResult {
456460 if let Some ( LObject :: Building ( building) ) = self . target . get ( state) . obj ( ) {
457461 let address = self . address . get ( state) ;
458462 let value = self . value . get_inner ( state, & state. variables ) ;
459463
460464 borrow_data ! (
461- mut Rc :: clone ( & building. data) ,
465+ mut building. data,
462466 state => {
463467 if let Some ( LObject :: String ( name) ) = address. into_owned( ) . obj( ) {
464468 // @counter should never be in state.variables, since globals are checked first
@@ -473,16 +477,24 @@ impl SimpleInstructionTrait for Write {
473477 }
474478 }
475479 } ,
476- data => {
477- if let BuildingData :: Memory ( memory) = data
478- && let Ok ( address) = address. num_usize( )
479- && address < memory. len( )
480- {
481- memory[ address] = value. num( ) ;
480+ data => match data {
481+ BuildingData :: Memory ( memory) => {
482+ if let Ok ( address) = address. num_usize( )
483+ && address < memory. len( )
484+ {
485+ memory[ address] = value. num( ) ;
486+ }
482487 }
483- } ,
488+
489+ BuildingData :: Custom ( custom) => {
490+ return custom. write( state, vm, address. into_owned( ) , value. into_owned( ) ) ;
491+ }
492+
493+ _ => { }
494+ }
484495 ) ;
485496 }
497+ InstructionResult :: Ok
486498 }
487499}
488500
@@ -595,19 +607,31 @@ pub struct PrintFlush {
595607 pub target : LVar ,
596608}
597609
598- impl SimpleInstructionTrait for PrintFlush {
599- fn execute ( & self , state : & mut ProcessorState , _ : & LogicVM ) {
600- if let Some ( LObject :: Building ( target) ) =
610+ impl InstructionTrait for PrintFlush {
611+ fn execute ( & self , state : & mut ProcessorState , vm : & LogicVM ) -> InstructionResult {
612+ let result = if let Some ( LObject :: Building ( target) ) =
601613 self . target . get_inner ( state, & state. variables ) . obj ( )
602- && let Ok ( mut data) = target. data . try_borrow_mut ( )
603- && let BuildingData :: Message ( message_buffer) = & mut * data
614+ && let Ok ( mut data) = target. data . clone ( ) . try_borrow_mut ( )
604615 {
605616 if state. printbuffer . len ( ) > MAX_TEXT_BUFFER {
606617 state. printbuffer . drain ( MAX_TEXT_BUFFER ..) ;
607618 }
608- core:: mem:: swap ( & mut state. printbuffer , message_buffer) ;
609- }
619+
620+ match & mut * data {
621+ BuildingData :: Message ( message_buffer) => {
622+ core:: mem:: swap ( & mut state. printbuffer , message_buffer) ;
623+ InstructionResult :: Ok
624+ }
625+
626+ BuildingData :: Custom ( custom) => custom. printflush ( state, vm) ,
627+
628+ _ => InstructionResult :: Ok ,
629+ }
630+ } else {
631+ InstructionResult :: Ok
632+ } ;
610633 state. printbuffer . clear ( ) ;
634+ result
611635 }
612636}
613637
@@ -637,28 +661,40 @@ pub struct Control {
637661 pub control : LAccess ,
638662 pub target : LVar ,
639663 pub p1 : LVar ,
664+ pub p2 : LVar ,
665+ pub p3 : LVar ,
640666}
641667
642- impl SimpleInstructionTrait for Control {
643- fn execute ( & self , state : & mut ProcessorState , _: & LogicVM ) {
644- if self . control == LAccess :: Enabled
645- && let Some ( LObject :: Building ( building) ) = self . target . get ( state) . obj ( )
668+ impl InstructionTrait for Control {
669+ fn execute ( & self , state : & mut ProcessorState , vm : & LogicVM ) -> InstructionResult {
670+ if let Some ( LObject :: Building ( building) ) = self . target . get ( state) . obj ( )
646671 && ( state. privileged ( ) || state. linked_positions ( ) . contains ( & building. position ) )
647672 {
648- let enabled = self . p1 . get ( state) ;
649- if enabled. isnum ( ) {
650- let enabled = enabled. numf ( ) != 0. ;
651- borrow_data ! (
652- mut Rc :: clone( & building. data) ,
653- state => state. set_enabled( enabled) ,
654- data => {
655- if let BuildingData :: Switch ( value) = data {
656- * value = enabled;
673+ borrow_data ! (
674+ mut building. data,
675+ state => if self . control == LAccess :: Enabled {
676+ let enabled = self . p1. get( state) ;
677+ if enabled. isnum( ) {
678+ state. set_enabled( enabled. numf( ) != 0. ) ;
679+ }
680+ } ,
681+ data => match data {
682+ BuildingData :: Switch ( value) if self . control == LAccess :: Enabled => {
683+ let enabled = self . p1. get( state) ;
684+ if enabled. isnum( ) {
685+ * value = enabled. numf( ) != 0. ;
657686 }
658- } ,
659- ) ;
660- }
687+ }
688+
689+ BuildingData :: Custom ( custom) => {
690+ return custom. control( state, vm, self . control, & self . p1, & self . p2, & self . p3) ;
691+ }
692+
693+ _ => { }
694+ } ,
695+ ) ;
661696 }
697+ InstructionResult :: Ok
662698 }
663699}
664700
@@ -671,7 +707,7 @@ pub struct Sensor {
671707}
672708
673709impl SimpleInstructionTrait for Sensor {
674- fn execute ( & self , state : & mut ProcessorState , _ : & LogicVM ) {
710+ fn execute ( & self , state : & mut ProcessorState , vm : & LogicVM ) {
675711 use LAccess :: * ;
676712
677713 let target = self . target . get ( state) ;
@@ -699,9 +735,9 @@ impl SimpleInstructionTrait for Sensor {
699735
700736 let result = match sensor. obj ( ) {
701737 // normal sensors
702- Some ( LObject :: Sensor ( sensor) ) => match target. obj ( ) {
738+ & Some ( LObject :: Sensor ( sensor) ) => match target. obj ( ) {
703739 // dead
704- Some ( LObject :: Null ) if * sensor == Dead => true . into ( ) ,
740+ Some ( LObject :: Null ) if sensor == Dead => true . into ( ) ,
705741
706742 // senseable
707743 Some ( LObject :: Content ( content) ) => match content {
@@ -768,7 +804,7 @@ impl SimpleInstructionTrait for Sensor {
768804 PayloadType => setnull ! ( ) ,
769805
770806 _ => borrow_data ! (
771- building. data. clone ( ) ,
807+ mut building. data,
772808 state => match sensor {
773809 LAccess :: Enabled => state. enabled( ) . into( ) ,
774810 _ => setnull!( ) ,
@@ -805,7 +841,16 @@ impl SimpleInstructionTrait for Sensor {
805841 _ => setnull!( ) ,
806842 } ,
807843
808- BuildingData :: Custom ( _) => setnull!( ) ,
844+ BuildingData :: Custom ( custom) => {
845+ match custom. sensor( state, vm, sensor) {
846+ Some ( value) => {
847+ self . result. set( state, value) ;
848+ return ;
849+ }
850+ None if sensor == Enabled => true . into( ) ,
851+ None => setnull!( ) ,
852+ }
853+ } ,
809854
810855 BuildingData :: Processor ( _) => unreachable!( ) ,
811856 } ,
0 commit comments