private LocalEnvironment joinEnvironments ( Context ... contexts ) { // Context head = contexts [ 0 ] ; GlobalEnvironment global = head . getEnvironment ( ) . getParent ( ) ; HashSet < WyilFile . Decl . Variable > modified = new HashSet <> ( ) ; HashSet < WyilFile . Decl . Variable > deleted = new HashSet <> ( ) ; Map < WyilFile . Decl . Variable , WyalFile . VariableDeclaration > headLocals = head . environment . locals ; // Compute the modified and deleted sets for ( int i = 1 ; i < contexts . length ; ++ i ) { Context ithContext = contexts [ i ] ; Map < WyilFile . Decl . Variable , WyalFile . VariableDeclaration > ithLocals = ithContext . environment . locals ; // First check env against head for ( Map . Entry < WyilFile . Decl . Variable , WyalFile . VariableDeclaration > e : ithLocals . entrySet ( ) ) { WyilFile . Decl . Variable key = e . getKey ( ) ; WyalFile . VariableDeclaration s1 = e . getValue ( ) ; WyalFile . VariableDeclaration s2 = headLocals . get ( key ) ; if ( s1 == null ) { deleted . add ( key ) ; } else if ( ! s1 . equals ( s2 ) ) { modified . add ( key ) ; } } // Second, check head against env for ( Map . Entry < WyilFile . Decl . Variable , WyalFile . VariableDeclaration > e : headLocals . entrySet ( ) ) { WyilFile . Decl . Variable key = e . getKey ( ) ; WyalFile . VariableDeclaration s1 = e . getValue ( ) ; WyalFile . VariableDeclaration s2 = ithLocals . get ( key ) ; if ( s1 == null ) { deleted . add ( key ) ; } else if ( ! s1 . equals ( s2 ) ) { modified . add ( key ) ; } } } // Finally, construct the combined local map IdentityHashMap < WyilFile . Decl . Variable , WyalFile . VariableDeclaration > combinedLocals = new IdentityHashMap <> ( ) ; for ( Map . Entry < WyilFile . Decl . Variable , WyalFile . VariableDeclaration > e : headLocals . entrySet ( ) ) { WyilFile . Decl . Variable key = e . getKey ( ) ; WyalFile . VariableDeclaration value = e . getValue ( ) ; if ( deleted . contains ( key ) ) { // Ignore this entry. This must be checked before we look at // modified (since variable can be marked both). continue ; } else if ( modified . contains ( key ) ) { // Update version number value = global . allocateVersion ( key ) ; } combinedLocals . put ( key , value ) ; } // Now, use the modified and deleted sets to build the new environment return new LocalEnvironment ( global , combinedLocals ) ; }
Join the local environments of one or more context s together . This means retaining variable versions which are the same for all context s allocating new versions for those which are different in at least one case and removing those which aren t present it at least one .