@@ -10,8 +10,8 @@ use base::{
1010use super :: ast:: {
1111 ArithmeticExpression , Atom , CommaDelimitedInstruction , Commas , ConfigValue , EqualityValue ,
1212 HoldBit , InstructionFragment , LiteralValue , LocatedBlock , Operator , RcAllocator , RcWordSource ,
13- SignedAtom , Statement , SymbolOrLiteral , Tag , TaggedProgramInstruction ,
14- UntaggedProgramInstruction ,
13+ RegisterContaining , RegistersContaining , SignedAtom , Statement , SymbolOrLiteral , Tag ,
14+ TaggedProgramInstruction , UntaggedProgramInstruction ,
1515} ;
1616use super :: listing:: { Listing , ListingLine } ;
1717use super :: span:: * ;
@@ -394,19 +394,20 @@ impl Evaluate for InstructionFragment {
394394 // of Q and ₜ were combined into the two parts of the
395395 // rc_word_value tuple. We evaluate Qₜ as
396396 // rc_word_val.
397- let ( base, index) = rc_word_value. as_ref ( ) ;
398- let base_value =
399- base. evaluate ( * rc_word_span, target_address, symtab, rc_allocator, op) ?;
400- let index_value =
401- index. evaluate ( * rc_word_span, target_address, symtab, rc_allocator, op) ?;
402- let rc_word_val: Unsigned36Bit = combine_fragment_values ( base_value, index_value) ;
403397 let p_value: Unsigned36Bit =
404398 p. item
405399 . evaluate ( p. span , target_address, symtab, rc_allocator, op) ?;
406- let rc_source = RcWordSource :: PipeConstruct ( * rc_word_span) ;
407- let addr: Address = rc_allocator. allocate ( rc_source, rc_word_val) ;
400+ let source_and_val: ( & RcWordSource , & RegisterContaining ) =
401+ ( & RcWordSource :: PipeConstruct ( * rc_word_span) , rc_word_value) ;
402+ let rc_word_addr: Unsigned36Bit = source_and_val. evaluate (
403+ * rc_word_span,
404+ target_address,
405+ symtab,
406+ rc_allocator,
407+ op,
408+ ) ?;
408409 Ok ( combine_fragment_values (
409- combine_fragment_values ( Unsigned36Bit :: from ( addr ) , p_value ) ,
410+ combine_fragment_values ( p_value , rc_word_addr ) ,
410411 DEFER_BIT ,
411412 ) )
412413 }
@@ -467,44 +468,10 @@ impl Evaluate for Atom {
467468 Atom :: Parens ( span, _script, expr) => {
468469 expr. evaluate ( * span, target_address, symtab, rc_allocator, op)
469470 }
470- Atom :: RcRef ( span, tagged_program_instructions) => {
471- let mut first_addr: Option < Address > = None ;
472- for inst in tagged_program_instructions. iter ( ) {
473- let rc_source = RcWordSource :: Braces ( * span) ;
474- let rc_word_addr: Address =
475- rc_allocator. allocate ( rc_source, Unsigned36Bit :: ZERO ) ;
476- if first_addr. is_none ( ) {
477- first_addr = Some ( rc_word_addr) ;
478- }
479-
480- // Within the RC-word, # ("here") resolves to the
481- // address of the RC-word itself. So before we
482- // evaluate the value to be placed in the RC-word,
483- // we need to know the value that # will take
484- // during the evaluation process.
485- let here = HereValue :: Address ( rc_word_addr) ;
486-
487- // If inst has a tag, we temporarily override any
488- // global value for that tag with the address of
489- // this instruction.
490- let tag_override: Option < ( & Tag , Address ) > =
491- inst. tag . as_ref ( ) . map ( |t| ( t, rc_word_addr) ) ;
492- let value: Unsigned36Bit = symtab. evaluate_with_temporary_tag_override (
493- tag_override,
494- inst,
495- inst. span ( ) ,
496- & here,
497- rc_allocator,
498- op,
499- ) ?;
500- rc_allocator. update ( rc_word_addr, value) ;
501- }
502- match first_addr {
503- Some ( addr) => Ok ( addr. into ( ) ) ,
504- None => {
505- unreachable ! ( "RC-references should not occupy zero words of storage" ) ;
506- }
507- }
471+ Atom :: RcRef ( span, registers_containing) => {
472+ let source_and_val: ( & RcWordSource , & RegistersContaining ) =
473+ ( & RcWordSource :: Braces ( * span) , registers_containing) ;
474+ source_and_val. evaluate ( * span, target_address, symtab, rc_allocator, op)
508475 }
509476 }
510477 }
@@ -1184,3 +1151,82 @@ impl LocatedBlock {
11841151 Ok ( words)
11851152 }
11861153}
1154+
1155+ impl Evaluate for ( & RcWordSource , & RegistersContaining ) {
1156+ fn evaluate < R : RcAllocator > (
1157+ & self ,
1158+ span : Span ,
1159+ _target_address : & HereValue ,
1160+ symtab : & mut SymbolTable ,
1161+ rc_allocator : & mut R ,
1162+ op : & mut LookupOperation ,
1163+ ) -> Result < Unsigned36Bit , SymbolLookupFailure > {
1164+ let rc_source: & RcWordSource = self . 0 ;
1165+ let registers_containing: & RegistersContaining = self . 1 ;
1166+ let mut first_addr: Option < Unsigned36Bit > = None ;
1167+ for rc_word in registers_containing. words ( ) {
1168+ // Evaluation of the RegisterContaining value will compute
1169+ // a correct here-value, we don't need to pass it in. But
1170+ // we can't pass None, and so instead we pass NotAllowed
1171+ // so that if a bug is introduced we will see a failure
1172+ // rather than an incorrect result.
1173+ let must_recompute_here_address = HereValue :: NotAllowed ;
1174+ let addr: Unsigned36Bit = ( rc_source, rc_word) . evaluate (
1175+ span,
1176+ & must_recompute_here_address,
1177+ symtab,
1178+ rc_allocator,
1179+ op,
1180+ ) ?;
1181+ if first_addr. is_none ( ) {
1182+ first_addr = Some ( addr) ;
1183+ }
1184+ }
1185+ match first_addr {
1186+ Some ( addr) => Ok ( addr) ,
1187+ None => {
1188+ unreachable ! ( "RC-references should not occupy zero words of storage" ) ;
1189+ }
1190+ }
1191+ }
1192+ }
1193+
1194+ impl Evaluate for ( & RcWordSource , & RegisterContaining ) {
1195+ fn evaluate < R : RcAllocator > (
1196+ & self ,
1197+ _span : Span ,
1198+ _target_address : & HereValue ,
1199+ symtab : & mut SymbolTable ,
1200+ rc_allocator : & mut R ,
1201+ op : & mut LookupOperation ,
1202+ ) -> Result < Unsigned36Bit , SymbolLookupFailure > {
1203+ let rc_source: & RcWordSource = self . 0 ;
1204+ let register_containing: & RegisterContaining = self . 1 ;
1205+
1206+ let rc_word_addr: Address = rc_allocator. allocate ( rc_source. clone ( ) , Unsigned36Bit :: ZERO ) ;
1207+ dbg ! ( & ( rc_source, rc_word_addr) ) ;
1208+
1209+ // Within the RC-word, # ("here") resolves to the
1210+ // address of the RC-word itself. So before we
1211+ // evaluate the value to be placed in the RC-word,
1212+ // we need to know the value that # will take
1213+ // during the evaluation process.
1214+ let here = HereValue :: Address ( rc_word_addr) ;
1215+
1216+ // If inst has a tag, we temporarily override any
1217+ // global value for that tag with the address of
1218+ // this instruction.
1219+ let inst: & TaggedProgramInstruction = register_containing. instruction ( ) ;
1220+ let tag_override: Option < ( & Tag , Address ) > = inst. tag . as_ref ( ) . map ( |t| ( t, rc_word_addr) ) ;
1221+ let value: Unsigned36Bit = symtab. evaluate_with_temporary_tag_override (
1222+ tag_override,
1223+ inst,
1224+ inst. span ( ) ,
1225+ & here,
1226+ rc_allocator,
1227+ op,
1228+ ) ?;
1229+ rc_allocator. update ( rc_word_addr, value) ;
1230+ Ok ( Unsigned36Bit :: from ( rc_word_addr) )
1231+ }
1232+ }
0 commit comments