@@ -109,87 +109,141 @@ public static ImStmt translate(StmtForIn forIn, ImTranslator t, ImFunction f) {
109109 if (itrType instanceof WurstTypeVararg ) {
110110 return case_StmtForVararg (forIn , t , f );
111111 }
112- List <ImStmt > result = Lists .newArrayList ();
112+ List <ImStmt > result = com . google . common . collect . Lists .newArrayList ();
113113
114114 Optional <FuncLink > iteratorFuncOpt = forIn .attrIteratorFunc ();
115115 Optional <FuncLink > nextFuncOpt = forIn .attrGetNextFunc ();
116116 Optional <FuncLink > hasNextFuncOpt = forIn .attrHasNextFunc ();
117+
117118 if (iteratorFuncOpt .isPresent () && nextFuncOpt .isPresent () && hasNextFuncOpt .isPresent ()) {
118119 FuncLink iteratorFunc = iteratorFuncOpt .get ();
119120 FuncLink nextFunc = nextFuncOpt .get ();
120121 FuncLink hasNextFunc = hasNextFuncOpt .get ();
121122
122- // Type of loop Variable :
123- WurstType loopVarType = forIn .getLoopVar ().attrTyp ();
123+ // Type of loop variable (element type S) :
124+ WurstType elemType = forIn .getLoopVar ().attrTyp ();
124125
125- // get the iterator function in the intermediate language
126+ // IM functions
126127 ImFunction iteratorFuncIm = t .getFuncFor (iteratorFunc .getDef ());
127- ImFunction nextFuncIm = t .getFuncFor (nextFunc .getDef ());
128- ImFunction hasNextFuncIm = t .getFuncFor (hasNextFunc .getDef ());
128+ ImFunction nextFuncIm = t .getFuncFor (nextFunc .getDef ());
129+ ImFunction hasNextFuncIm = t .getFuncFor (hasNextFunc .getDef ());
129130
130- // translate target:
131+ // Translate receiver (iteration target) :
131132 ImExprs iterationTargetList ;
132- if (forIn . getIn (). attrTyp () .isStaticRef ()) {
133+ if (itrType .isStaticRef ()) {
133134 iterationTargetList = ImExprs ();
134135 } else {
135- ImExpr iterationTargetIm = forIn . getIn () .imTranslateExpr (t , f );
136+ ImExpr iterationTargetIm = iterationTarget .imTranslateExpr (t , f );
136137 iterationTargetList = JassIm .ImExprs (iterationTargetIm );
137138 }
138139
139- // call XX.iterator()
140- ImFunctionCall iteratorCall = ImFunctionCall (forIn , iteratorFuncIm , ImTypeArguments (), iterationTargetList , false , CallType .NORMAL );
141- // create IM-variable for iterator
142- ImVar iteratorVar = JassIm .ImVar (forIn .getLoopVar (), iteratorCall .attrTyp (), "iterator" , false );
140+ // --- CONCRETE type argument for Iterator<S> and its methods ---
141+ ImType elemImType = elemType .imTranslateType (t );
142+ ImTypeArguments iterTypeArgs = JassIm .ImTypeArguments (
143+ JassIm .ImTypeArgument (elemImType , java .util .Collections .emptyMap ())
144+ );
145+
146+ // call XX.iterator()<S>()
147+ ImFunctionCall iteratorCall = ImFunctionCall (
148+ forIn , iteratorFuncIm , iterTypeArgs , iterationTargetList , false , CallType .NORMAL
149+ );
150+
151+ // Materialize a concrete IM class type for the iterator local (Iterator<S>)
152+ ImType iteratorImType ;
153+ WurstType retWT = iteratorFunc .getReturnType ().normalize ();
154+ if (retWT instanceof de .peeeq .wurstscript .types .WurstTypeClass ) {
155+ de .peeeq .wurstscript .types .WurstTypeClass rtc = (de .peeeq .wurstscript .types .WurstTypeClass ) retWT ;
156+ de .peeeq .wurstscript .ast .ClassDef rtClassDef = rtc .getClassDef ();
157+ ImClass imIterClass = t .getClassFor (rtClassDef );
158+ iteratorImType = JassIm .ImClassType (imIterClass , iterTypeArgs .copy ());
159+ } else {
160+ // fallback – should not happen for a well-formed iterator()
161+ iteratorImType = retWT .imTranslateType (t );
162+ }
143163
164+ // locals: iterator and loopVar
165+ ImVar iteratorVar = JassIm .ImVar (forIn .getLoopVar (), iteratorImType , "iterator" , false );
144166 f .getLocals ().add (iteratorVar );
145167 f .getLocals ().add (t .getVarFor (forIn .getLoopVar ()));
146- // create code for initializing iterator:
147168
148- ImSet setIterator = ImSet (forIn , ImVarAccess (iteratorVar ), iteratorCall );
149-
150- result .add (setIterator );
169+ // init iterator
170+ result .add (ImSet (forIn , ImVarAccess (iteratorVar ), iteratorCall ));
151171
152172 ImStmts imBody = ImStmts ();
153- // exitwhen not #hasNext()
154- imBody .add (ImExitwhen (forIn , JassIm .ImOperatorCall (WurstOperator .NOT , JassIm .ImExprs (ImFunctionCall (forIn , hasNextFuncIm , ImTypeArguments (), JassIm .ImExprs
155- (JassIm
156- .ImVarAccess (iteratorVar )), false , CallType .NORMAL )))));
157- // elem = next()
158- ImFunctionCall nextCall = ImFunctionCall (forIn , nextFuncIm , ImTypeArguments (), JassIm .ImExprs (JassIm .ImVarAccess (iteratorVar )), false , CallType .NORMAL );
159- WurstType nextReturn = nextFunc .getReturnType ();
160- ImExpr nextCallWrapped = ExprTranslation .wrapTranslation (forIn , t , nextCall , nextReturn , loopVarType );
173+
174+ // exitwhen not iterator.hasNext()<S>()
175+ imBody .add (ImExitwhen (
176+ forIn ,
177+ JassIm .ImOperatorCall (
178+ de .peeeq .wurstscript .WurstOperator .NOT ,
179+ JassIm .ImExprs (
180+ ImFunctionCall (
181+ forIn , hasNextFuncIm , iterTypeArgs .copy (),
182+ JassIm .ImExprs (JassIm .ImVarAccess (iteratorVar )),
183+ false , CallType .NORMAL
184+ )
185+ )
186+ )
187+ ));
188+
189+ // elem = iterator.next()<S>()
190+ ImFunctionCall nextCall = ImFunctionCall (
191+ forIn , nextFuncIm , iterTypeArgs .copy (),
192+ JassIm .ImExprs (JassIm .ImVarAccess (iteratorVar )),
193+ false , CallType .NORMAL
194+ );
195+
196+ ImExpr nextCallWrapped = de .peeeq .wurstscript .translation .imtranslation .ExprTranslation
197+ .wrapTranslation (forIn , t , nextCall , nextFunc .getReturnType (), elemType );
161198
162199 imBody .add (ImSet (forIn , ImVarAccess (t .getVarFor (forIn .getLoopVar ())), nextCallWrapped ));
163200
201+ // loop body
164202 imBody .addAll (t .translateStatements (f , forIn .getBody ()));
165203
204+ // optional close()<S>()
166205 Optional <FuncLink > closeFunc = forIn .attrCloseFunc ();
167206 closeFunc .ifPresent (funcLink -> {
168-
169- // close iterator before each return
170207 imBody .accept (new de .peeeq .wurstscript .jassIm .Element .DefaultVisitor () {
171208 @ Override
172209 public void visit (ImReturn imReturn ) {
173210 super .visit (imReturn );
174- imReturn .replaceBy (ImHelper .statementExprVoid (JassIm .ImStmts (ImFunctionCall (forIn , t .getFuncFor (funcLink .getDef ()), ImTypeArguments (), JassIm
175- .ImExprs (JassIm .ImVarAccess (iteratorVar )), false , CallType .NORMAL ), imReturn .copy ())));
211+ imReturn .replaceBy (
212+ ImHelper .statementExprVoid (
213+ JassIm .ImStmts (
214+ ImFunctionCall (
215+ forIn , t .getFuncFor (funcLink .getDef ()),
216+ iterTypeArgs .copy (),
217+ JassIm .ImExprs (JassIm .ImVarAccess (iteratorVar )),
218+ false , CallType .NORMAL
219+ ),
220+ imReturn .copy ()
221+ )
222+ )
223+ );
176224 }
177-
178225 });
179-
180226 });
181227
182228 result .add (ImLoop (forIn , imBody ));
183- // close iterator after loop
184- closeFunc .ifPresent (nameLink -> result .add (ImFunctionCall (forIn , t .getFuncFor (nameLink .getDef ()), ImTypeArguments (), JassIm .ImExprs (JassIm
185- .ImVarAccess (iteratorVar )), false , CallType .NORMAL )));
186229
230+ // close after loop
231+ closeFunc .ifPresent (nameLink ->
232+ result .add (
233+ ImFunctionCall (
234+ forIn , t .getFuncFor (nameLink .getDef ()),
235+ iterTypeArgs .copy (),
236+ JassIm .ImExprs (JassIm .ImVarAccess (iteratorVar )),
237+ false , CallType .NORMAL
238+ )
239+ )
240+ );
187241 }
188242
189-
190243 return ImHelper .statementExprVoid (ImStmts (result ));
191244 }
192245
246+
193247 /**
194248 * Translate a for in vararg loop. Unlike the other for loops we don't need
195249 * an iterator etc. because the loop is unrolled in the VarargEliminator
0 commit comments