@@ -11,6 +11,7 @@ public class LinearTypeChecker : ReadOnlyVisitor
1111
1212 public Program program ;
1313 private CheckingContext checkingContext ;
14+ private HashSet < ( Absy , string ) > errors ;
1415 private CivlTypeChecker civlTypeChecker ;
1516 private Dictionary < Type , ActionDecl > pendingAsyncTypeToActionDecl ;
1617 private Dictionary < Type , LinearDomain > permissionTypeToLinearDomain ;
@@ -22,6 +23,7 @@ public LinearTypeChecker(CivlTypeChecker civlTypeChecker)
2223 this . civlTypeChecker = civlTypeChecker ;
2324 this . program = civlTypeChecker . program ;
2425 this . checkingContext = civlTypeChecker . checkingContext ;
26+ this . errors = new ( ) ;
2527 this . pendingAsyncTypeToActionDecl = new ( ) ;
2628 foreach ( var actionDecl in program . TopLevelDeclarations . OfType < ActionDecl > ( ) . Where ( actionDecl => actionDecl . MaybePendingAsync ) )
2729 {
@@ -39,6 +41,11 @@ public LinearTypeChecker(CivlTypeChecker civlTypeChecker)
3941
4042 private void Error ( Absy node , string message )
4143 {
44+ if ( errors . Contains ( ( node , message ) ) )
45+ {
46+ return ;
47+ }
48+ errors . Add ( ( node , message ) ) ;
4249 checkingContext . Error ( node , message ) ;
4350 }
4451
@@ -125,15 +132,13 @@ private HashSet<Variable> PropagateAvailableLinearVarsAcrossBlock(Block b)
125132 {
126133 continue ;
127134 }
128- // assignment may violate the disjointness invariant
129- // therefore, drop lhsVar from the set of available variables
130- // but possibly add it to lhsVarsToAdd (added to start later)
131135 var lhsVar = lhs . DeepAssignedVariable ;
132- start . Remove ( lhsVar ) ;
133136 var rhsExpr = assignCmd . Rhss [ i ] ;
134137 if ( rhsExpr is IdentifierExpr ie )
135138 {
136- if ( start . Contains ( ie . Decl ) )
139+ var rhsIsAvailable = start . Contains ( ie . Decl ) ;
140+ start . Remove ( lhsVar ) ;
141+ if ( rhsIsAvailable )
137142 {
138143 start . Remove ( ie . Decl ) ;
139144 lhsVarsToAdd . Add ( lhsVar ) ;
@@ -143,38 +148,32 @@ private HashSet<Variable> PropagateAvailableLinearVarsAcrossBlock(Block b)
143148 ! IsPrimitiveLinearType ( rhsExpr . Type ) )
144149 {
145150 // pack
146- bool addLhsVar = true ;
147- for ( int j = 0 ; j < constructor . InParams . Count ; j ++ )
148- {
149- var field = constructor . InParams [ j ] ;
150- if ( IsOrdinaryType ( field . TypedIdent . Type ) )
151- {
152- continue ;
153- }
154- var arg = ( IdentifierExpr ) nAryExpr . Args [ j ] ;
155- if ( start . Contains ( arg . Decl ) )
156- {
157- start . Remove ( arg . Decl ) ;
158- }
159- else
160- {
161- addLhsVar = false ;
162- }
163- }
164- if ( addLhsVar )
151+ var linearArgs = constructor . InParams . Zip ( nAryExpr . Args )
152+ . Where ( x => ! IsOrdinaryType ( x . First . TypedIdent . Type ) )
153+ . Select ( x => x . Second ) . OfType < IdentifierExpr > ( ) ;
154+ bool rhsIsAvailable = linearArgs . All ( ie => start . Contains ( ie . Decl ) ) ;
155+ start . Remove ( lhsVar ) ;
156+ if ( rhsIsAvailable )
165157 {
158+ linearArgs . ForEach ( ie => { start . Remove ( ie . Decl ) ; } ) ;
166159 lhsVarsToAdd . Add ( lhsVar ) ;
167160 }
168161 }
162+ else
163+ {
164+ start . Remove ( lhsVar ) ;
165+ }
169166 }
170167 start . UnionWith ( lhsVarsToAdd ) ;
171168 }
172169 else if ( cmd is UnpackCmd unpackCmd )
173170 {
174171 if ( ! IsOrdinaryType ( unpackCmd . Rhs . Type ) )
175172 {
176- var ie = unpackCmd . Rhs as IdentifierExpr ;
177- if ( start . Contains ( ie . Decl ) )
173+ var ie = ( IdentifierExpr ) unpackCmd . Rhs ;
174+ var rhsIsAvailable = start . Contains ( ie . Decl ) ;
175+ unpackCmd . UnpackedLhs . ForEach ( arg => start . Remove ( arg . Decl ) ) ;
176+ if ( rhsIsAvailable )
178177 {
179178 start . Remove ( ie . Decl ) ;
180179 unpackCmd . UnpackedLhs
@@ -217,7 +216,7 @@ private HashSet<Variable> PropagateAvailableLinearVarsAcrossBlock(Block b)
217216 }
218217 else
219218 {
220- Error ( ie , $ "unavailable source { ie } for linear parameter at position { i } ") ;
219+ Error ( callCmd , $ "unavailable source { ie } for linear parameter at position { i } ") ;
221220 }
222221 }
223222 var originalProc = ( Procedure ) Monomorphizer . GetOriginalDecl ( callCmd . Proc ) ;
@@ -273,7 +272,7 @@ private HashSet<Variable> PropagateAvailableLinearVarsAcrossBlock(Block b)
273272 }
274273 else
275274 {
276- Error ( ie , $ "unavailable source { ie } for linear parameter at position { i } ") ;
275+ Error ( parCallCallCmd , $ "unavailable source { ie } for linear parameter at position { i } ") ;
277276 }
278277 }
279278 }
@@ -727,15 +726,17 @@ public static LinearKind FindLinearKind(Variable v)
727726 public int CheckLinearParameters ( CallCmd callCmd , HashSet < Variable > availableLinearVarsAtCallCmd )
728727 {
729728 int errorCount = 0 ;
730- foreach ( var ( ie , formal ) in callCmd . Ins . Zip ( callCmd . Proc . InParams ) )
729+ for ( int i = 0 ; i < callCmd . Ins . Count ; i ++ )
731730 {
731+ var ie = callCmd . Ins [ i ] ;
732+ var formal = callCmd . Proc . InParams [ i ] ;
732733 if ( FindLinearKind ( formal ) == LinearKind . ORDINARY )
733734 {
734735 continue ;
735736 }
736737 if ( ie is IdentifierExpr actual && ! availableLinearVarsAtCallCmd . Contains ( actual . Decl ) )
737738 {
738- Error ( actual , "argument must be available ") ;
739+ Error ( callCmd , $ "unavailable source { ie } for linear parameter at position { i } ") ;
739740 errorCount ++ ;
740741 }
741742 }
0 commit comments