@@ -22,6 +22,7 @@ import {
2222 BasicBlock ,
2323 isUseRefType ,
2424 SourceLocation ,
25+ ArrayExpression ,
2526} from '../HIR' ;
2627import { eachInstructionLValue , eachInstructionOperand } from '../HIR/visitors' ;
2728import { isMutable } from '../ReactiveScopes/InferReactiveScopeVariables' ;
@@ -36,11 +37,17 @@ type DerivationMetadata = {
3637 isStateSource : boolean ;
3738} ;
3839
40+ type EffectMetadata = {
41+ effect : HIRFunction ;
42+ dependencies : ArrayExpression ;
43+ } ;
44+
3945type ValidationContext = {
4046 readonly functions : Map < IdentifierId , FunctionExpression > ;
47+ readonly candidateDependencies : Map < IdentifierId , ArrayExpression > ;
4148 readonly errors : CompilerError ;
4249 readonly derivationCache : DerivationCache ;
43- readonly effects : Set < HIRFunction > ;
50+ readonly effectsCache : Map < IdentifierId , EffectMetadata > ;
4451 readonly setStateLoads : Map < IdentifierId , IdentifierId | null > ;
4552 readonly setStateUsages : Map < IdentifierId , Set < SourceLocation > > ;
4653} ;
@@ -175,18 +182,20 @@ export function validateNoDerivedComputationsInEffects_exp(
175182 fn : HIRFunction ,
176183) : Result < void , CompilerError > {
177184 const functions : Map < IdentifierId , FunctionExpression > = new Map ( ) ;
185+ const candidateDependencies : Map < IdentifierId , ArrayExpression > = new Map ( ) ;
178186 const derivationCache = new DerivationCache ( ) ;
179187 const errors = new CompilerError ( ) ;
180- const effects : Set < HIRFunction > = new Set ( ) ;
188+ const effectsCache : Map < IdentifierId , EffectMetadata > = new Map ( ) ;
181189
182190 const setStateLoads : Map < IdentifierId , IdentifierId > = new Map ( ) ;
183191 const setStateUsages : Map < IdentifierId , Set < SourceLocation > > = new Map ( ) ;
184192
185193 const context : ValidationContext = {
186194 functions,
195+ candidateDependencies,
187196 errors,
188197 derivationCache,
189- effects ,
198+ effectsCache ,
190199 setStateLoads,
191200 setStateUsages,
192201 } ;
@@ -229,8 +238,8 @@ export function validateNoDerivedComputationsInEffects_exp(
229238 isFirstPass = false ;
230239 } while ( context . derivationCache . snapshot ( ) ) ;
231240
232- for ( const effect of effects ) {
233- validateEffect ( effect , context ) ;
241+ for ( const [ , effect ] of effectsCache ) {
242+ validateEffect ( effect . effect , effect . dependencies , context ) ;
234243 }
235244
236245 return errors . asResult ( ) ;
@@ -354,8 +363,14 @@ function recordInstructionDerivations(
354363 value . args [ 1 ] . kind === 'Identifier'
355364 ) {
356365 const effectFunction = context . functions . get ( value . args [ 0 ] . identifier . id ) ;
357- if ( effectFunction != null ) {
358- context . effects . add ( effectFunction . loweredFunc . func ) ;
366+ const deps = context . candidateDependencies . get (
367+ value . args [ 1 ] . identifier . id ,
368+ ) ;
369+ if ( effectFunction != null && deps != null ) {
370+ context . effectsCache . set ( value . args [ 0 ] . identifier . id , {
371+ effect : effectFunction . loweredFunc . func ,
372+ dependencies : deps ,
373+ } ) ;
359374 }
360375 } else if ( isUseStateType ( lvalue . identifier ) && value . args . length > 0 ) {
361376 typeOfValue = 'fromState' ;
@@ -367,6 +382,8 @@ function recordInstructionDerivations(
367382 ) ;
368383 return ;
369384 }
385+ } else if ( value . kind === 'ArrayExpression' ) {
386+ context . candidateDependencies . set ( lvalue . identifier . id , value ) ;
370387 }
371388
372389 for ( const operand of eachInstructionOperand ( instr ) ) {
@@ -596,6 +613,7 @@ function getFnLocalDeps(
596613
597614function validateEffect (
598615 effectFunction : HIRFunction ,
616+ dependencies : ArrayExpression ,
599617 context : ValidationContext ,
600618) : void {
601619 const seenBlocks : Set < BlockId > = new Set ( ) ;
@@ -612,6 +630,16 @@ function validateEffect(
612630 Set < SourceLocation >
613631 > = new Map ( ) ;
614632
633+ // Consider setStates in the effect's dependency array as being part of effectSetStateUsages
634+ for ( const dep of dependencies . elements ) {
635+ if ( dep . kind === 'Identifier' ) {
636+ const usage = context . setStateUsages . get ( dep . identifier . id ) ;
637+ if ( usage !== undefined ) {
638+ effectSetStateUsages . set ( dep . identifier . id , usage ) ;
639+ }
640+ }
641+ }
642+
615643 let cleanUpFunctionDeps : Set < IdentifierId > | undefined ;
616644
617645 const globals : Set < IdentifierId > = new Set ( ) ;
0 commit comments