@@ -12,7 +12,10 @@ use base::prelude::*;
1212use crate :: eval:: { combine_fragment_values, HereValue , SymbolLookupFailure , SymbolValue } ;
1313use crate :: symtab:: LookupOperation ;
1414
15- use super :: eval:: { Evaluate , RcBlock , SymbolContext , SymbolDefinition , SymbolLookup , SymbolUse } ;
15+ use super :: eval:: {
16+ evaluate_tagged_program_instructions, Evaluate , RcBlock , SymbolContext , SymbolDefinition ,
17+ SymbolLookup , SymbolUse ,
18+ } ;
1619use super :: glyph;
1720use super :: span:: * ;
1821use super :: state:: NumeralMode ;
@@ -187,10 +190,18 @@ impl ArithmeticExpression {
187190 ArithmeticExpression { first, tail }
188191 }
189192
190- pub ( crate ) fn symbol_uses ( & self ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > {
193+ pub ( crate ) fn symbol_uses (
194+ & self ,
195+ block_id : BlockIdentifier ,
196+ block_offset : Unsigned18Bit ,
197+ ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > {
191198 let mut result = Vec :: with_capacity ( 1 + self . tail . len ( ) ) ;
192- result. extend ( self . first . symbol_uses ( ) ) ;
193- result. extend ( self . tail . iter ( ) . flat_map ( |( _op, x) | x. symbol_uses ( ) ) ) ;
199+ result. extend ( self . first . symbol_uses ( block_id, block_offset) ) ;
200+ result. extend (
201+ self . tail
202+ . iter ( )
203+ . flat_map ( |( _op, x) | x. symbol_uses ( block_id, block_offset) ) ,
204+ ) ;
194205 result. into_iter ( )
195206 }
196207
@@ -335,7 +346,7 @@ pub(crate) enum Atom {
335346 Literal ( LiteralValue ) ,
336347 Symbol ( Span , Script , SymbolOrHere ) ,
337348 Parens ( Script , Box < ArithmeticExpression > ) ,
338- RcRef ( Span , Vec < InstructionFragment > ) ,
349+ RcRef ( Span , Vec < TaggedProgramInstruction > ) ,
339350}
340351
341352impl From < SymbolOrLiteral > for Atom {
@@ -350,10 +361,14 @@ impl From<SymbolOrLiteral> for Atom {
350361}
351362
352363impl Atom {
353- pub ( crate ) fn symbol_uses ( & self ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > {
364+ pub ( crate ) fn symbol_uses (
365+ & self ,
366+ block_id : BlockIdentifier ,
367+ block_offset : Unsigned18Bit ,
368+ ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > {
354369 let mut result = Vec :: with_capacity ( 1 ) ;
355370 match self {
356- Atom :: Literal ( _) | Atom :: RcRef ( _ , _ ) | Atom :: Symbol ( _, _, SymbolOrHere :: Here ) => ( ) ,
371+ Atom :: Literal ( _) | Atom :: Symbol ( _, _, SymbolOrHere :: Here ) => ( ) ,
357372 Atom :: Symbol ( span, script, SymbolOrHere :: Named ( name) ) => {
358373 result. push ( (
359374 name. clone ( ) ,
@@ -362,7 +377,47 @@ impl Atom {
362377 ) ) ;
363378 }
364379 Atom :: Parens ( _script, expr) => {
365- result. extend ( expr. symbol_uses ( ) ) ;
380+ result. extend ( expr. symbol_uses ( block_id, block_offset) ) ;
381+ }
382+ Atom :: RcRef ( _span, tagged_instructions) => {
383+ // Tags defined inside the RC-word are not counted as
384+ // defined outside it. But if we refer to a symbol
385+ // inside the RC-word it counts as a reference for the
386+ // purpose of determining which contexts it has been
387+ // used in.
388+ for symbol_use in tagged_instructions
389+ . iter ( )
390+ . flat_map ( |instr| instr. symbol_uses ( block_id, block_offset) )
391+ {
392+ match & symbol_use {
393+ ( _, _, SymbolUse :: Reference ( _) ) => {
394+ result. push ( symbol_use) ;
395+ }
396+ ( name, _span, SymbolUse :: Definition ( SymbolDefinition :: Tag { .. } ) ) => {
397+ panic ! ( "Found definition of tag {name} inside an RC-word; this is allowed but is not yet supported." ) ;
398+ }
399+ ( name, _span, SymbolUse :: Origin ( _name, _block) ) => {
400+ unreachable ! ( "Found origin {name} inside an RC-word; the parser should have rejected this." ) ;
401+ }
402+ ( name, span, SymbolUse :: Definition ( _) ) => {
403+ // e.g. we have an input like
404+ //
405+ // { X = 2 }
406+ //
407+ //
408+ // Ideally we would issue an error for
409+ // this, but since this function cannot
410+ // fail, it's better to do that at the
411+ // time we parse the RC-word reference
412+ // (thus eliminating this case).
413+ //
414+ // When working on this case we should
415+ // figure out if an equality is allowed
416+ // inside a macro expansion.
417+ panic ! ( "Found unexpected definition of {name} inside RC-word reference at {span:?}" ) ;
418+ }
419+ }
420+ }
366421 }
367422 }
368423 result. into_iter ( )
@@ -410,9 +465,9 @@ impl Evaluate for Atom {
410465 op,
411466 ) ,
412467 Atom :: Parens ( _script, expr) => expr. evaluate ( target_address, symtab, rc_allocator, op) ,
413- Atom :: RcRef ( span, fragments ) => {
414- let value: Unsigned36Bit = evaluate_instruction_fragments (
415- fragments ,
468+ Atom :: RcRef ( span, tagged_program_instructions ) => {
469+ let value: Unsigned36Bit = evaluate_tagged_program_instructions (
470+ tagged_program_instructions ,
416471 target_address,
417472 symtab,
418473 rc_allocator,
@@ -544,11 +599,15 @@ pub(crate) enum InstructionFragment {
544599}
545600
546601impl InstructionFragment {
547- pub ( crate ) fn symbol_uses ( & self ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > {
602+ pub ( crate ) fn symbol_uses (
603+ & self ,
604+ block_id : BlockIdentifier ,
605+ block_offset : Unsigned18Bit ,
606+ ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > {
548607 let mut result: Vec < _ > = Vec :: new ( ) ;
549608 match self {
550609 InstructionFragment :: Arithmetic ( expr) => {
551- result. extend ( expr. symbol_uses ( ) ) ;
610+ result. extend ( expr. symbol_uses ( block_id , block_offset ) ) ;
552611 }
553612 InstructionFragment :: DeferredAddressing => ( ) ,
554613 InstructionFragment :: Config ( value) => {
@@ -567,8 +626,8 @@ impl InstructionFragment {
567626 ( name, span, symbol_use)
568627 } ) ) ;
569628 let ( base, index) = rc_word_value. as_ref ( ) ;
570- result. extend ( base. symbol_uses ( ) ) ;
571- result. extend ( index. symbol_uses ( ) ) ;
629+ result. extend ( base. symbol_uses ( block_id , block_offset ) ) ;
630+ result. extend ( index. symbol_uses ( block_id , block_offset ) ) ;
572631 }
573632 }
574633 result. into_iter ( )
@@ -783,8 +842,12 @@ impl CommaDelimitedInstruction {
783842 }
784843 }
785844
786- pub ( crate ) fn symbol_uses ( & self ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > + ' _ {
787- self . instruction . symbol_uses ( )
845+ pub ( crate ) fn symbol_uses (
846+ & self ,
847+ block_id : BlockIdentifier ,
848+ block_offset : Unsigned18Bit ,
849+ ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > + ' _ {
850+ self . instruction . symbol_uses ( block_id, block_offset)
788851 }
789852
790853 pub ( crate ) fn span ( & self ) -> Span {
@@ -1762,46 +1825,13 @@ pub(crate) struct UntaggedProgramInstruction {
17621825}
17631826
17641827impl UntaggedProgramInstruction {
1765- pub ( crate ) fn symbol_uses ( & self ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > + ' _ {
1766- self . inst . symbol_uses ( )
1767- }
1768- }
1769-
1770- fn evaluate_instruction_fragments < R : RcAllocator > (
1771- parts : & [ InstructionFragment ] ,
1772- target_address : & HereValue ,
1773- symtab : & mut SymbolTable ,
1774- rc_allocator : & mut R ,
1775- op : & mut LookupOperation ,
1776- ) -> Result < Unsigned36Bit , SymbolLookupFailure > {
1777- fn or_looked_up_value < R : RcAllocator > (
1778- accumulator : Unsigned36Bit ,
1779- frag : & InstructionFragment ,
1780- target_address : & HereValue ,
1781- symtab : & mut SymbolTable ,
1782- rc_allocator : & mut R ,
1783- op : & mut LookupOperation ,
1784- ) -> Result < Unsigned36Bit , SymbolLookupFailure > {
1785- Ok ( combine_fragment_values (
1786- accumulator,
1787- frag. evaluate ( target_address, symtab, rc_allocator, op) ?,
1788- ) )
1828+ pub ( crate ) fn symbol_uses (
1829+ & self ,
1830+ block_id : BlockIdentifier ,
1831+ block_offset : Unsigned18Bit ,
1832+ ) -> impl Iterator < Item = ( SymbolName , Span , SymbolUse ) > + ' _ {
1833+ self . inst . symbol_uses ( block_id, block_offset)
17891834 }
1790-
1791- parts. iter ( ) . try_fold ( Unsigned36Bit :: ZERO , |acc, curr| {
1792- or_looked_up_value ( acc, curr, target_address, symtab, rc_allocator, op)
1793- } )
1794- }
1795-
1796- fn evaluate_instruction_fragment < R : RcAllocator > (
1797- // TODO: fold into caller
1798- inst : & InstructionFragment ,
1799- target_address : & HereValue ,
1800- symtab : & mut SymbolTable ,
1801- rc_allocator : & mut R ,
1802- op : & mut LookupOperation ,
1803- ) -> Result < Unsigned36Bit , SymbolLookupFailure > {
1804- inst. evaluate ( target_address, symtab, rc_allocator, op)
18051835}
18061836
18071837impl Evaluate for UntaggedProgramInstruction {
@@ -1812,13 +1842,18 @@ impl Evaluate for UntaggedProgramInstruction {
18121842 rc_allocator : & mut R ,
18131843 op : & mut LookupOperation ,
18141844 ) -> Result < Unsigned36Bit , SymbolLookupFailure > {
1815- evaluate_instruction_fragment ( & self . inst , target_address, symtab, rc_allocator, op) . map (
1816- |word| match self . holdbit {
1845+ // TODO: issue a diagnostic if a TaggedProgramInstruction
1846+ // contains inconsistent values for the hold bit. We will need to decide
1847+ // whether something like ",h" sets the hold bit (i.e. whether
1848+ // the hold bit is supposed to be subject to the same
1849+ // comma rules that other values are).
1850+ self . inst
1851+ . evaluate ( target_address, symtab, rc_allocator, op)
1852+ . map ( |word| match self . holdbit {
18171853 HoldBit :: Hold => word | HELD_MASK ,
18181854 HoldBit :: NotHold => word & !HELD_MASK ,
18191855 HoldBit :: Unspecified => word,
1820- } ,
1821- )
1856+ } )
18221857 }
18231858}
18241859
@@ -1868,7 +1903,7 @@ impl TaggedProgramInstruction {
18681903 result. extend ( tag. symbol_uses ( block_id, offset) ) ;
18691904 }
18701905 for inst in self . instructions . iter ( ) {
1871- result. extend ( inst. symbol_uses ( ) ) ;
1906+ result. extend ( inst. symbol_uses ( block_id , offset ) ) ;
18721907 }
18731908 result. into_iter ( )
18741909 }
0 commit comments