C# - Ciklusok generálása

Futásidejű kódgenerálás 5. rész

forráskód letöltése
A sorozat eddigi számaiban megismert lehetőségek sorát kiegészítendő, újabb osztályok működését mutatjuk be a kódgenerálás témakörében. Megismerkedhetünk annak módjával, hogy miként lehet a generálandó forráskódba – a System.CodeDOM névtér speciális osztályait felhasználva – FOR ciklust létrehozni. A mellékelt példa segítségével a gyakorlatban is megnézhetjük az osztályok működését.
Ahogy tettük ezt a legutóbbi cikkben, most is az ott létrehozott példát fejlesztjük tovább. A példaalkalmazásban a Form első szövegmezőjében kell megadni a generálandó kód névterét, a másodikban a létrehozandó osztály nevét, melyeket majd a fordító is felhasznál.
A GENERÁLÁS gomb megnyomásával elkészíthetjük, a FORDÍTÁS gomb segítségével le is fordíthatjuk a kódállományt.
A paramétereket egy tömbben adjuk át a konstruktornak, melynek elemeit egy FOR ciklussal dolgozzuk fel. A FOR ciklus létrehozása megfelelő osztályok segítségével történik, a kód többi része változatlan. Az elkészült forrásállományban a megadott osztály konstruktorában, a TRY-CATCH blokkban a következő ciklusdeklaráció jelenik meg, dinamikusan generálva.
int i = 0;
for (i = 0; (i < param.Length); i = (i + 1)){
  act = Convert.ToInt32(param[i]);
  if (i != param.Length-1){
    result += act; res += act.ToString() + " + ";
  }
  if (i == param.Length-1){
    result += act; res += act.ToString() + " = " + result.ToString();
  }
}
A generált futtatható állomány elindításakor véletlenszám-generátor segítségével generálunk véletlen számú egész számot, melyeket paraméterként átadunk a programnak. A program kiírja az operandusokat, valamint az eredményt egy karakterláncba, majd vár egy billentyűleütésre a program bezárása előtt.
A ciklusok generálását a CodeIterationStatement osztály teszi lehetővé, melynek példányosításakor a konstruktor paraméterében kell megadni a ciklusváltozó deklarációját, a lépésközt, és egyéb, a helyes működéshez elengedhetetlen lépés deklarációját. A függvény szintaxisa a következő:
CodeIterationStatement
Osztály: CodeIterationStatement
public CodeIterationStatement(
CodeStatement initStatement,
CodeExpression testExpression,
CodeStatement incrementStatement,
params CodeStatement[] statements
);
Ciklus generáló osztály létrehozása. Az osztály használható a WHILE ciklusok generálására is.
Paraméterek
CodeStatement initStatement
Ciklusváltozó kezdeti értékadása.
CodeExpression testExpression
Ciklusfeltétel meghatározása.
CodeStatement incrementStatement
Ciklusváltozó léptetése.
params CodeStatement[] statements
Végrehajtandó utasítások listája.
CodeIterationStatement forloop = new CodeIterationStatement(
Elsőként értéket adunk az InitStatement property-nek, vagyis kezdőértéket adunk a korábban már deklarált ciklusváltozónak.
  new CodeAssignStatement(new CodeVariableReferenceExpression("i"), new CodePrimitiveExpression(0)),
Ezt követően megadjuk a ciklusfeltételt. Mivel a ciklus dolga lesz a PARAM nevű függvényparaméterből kivenni az operandusokat, a ciklus addig megy, amíg a ciklusváltozó értéke kisebb a paraméter tömb elemszámánál. A feltétel operátorát a CodeBinaryOperatorType felsorolt típus segítségével adjuk meg. A második paraméter az objektum TestExpression property-jének ad értéket.
  new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.LessThan, new CodeSnippetExpression("param.Length")),
Az IncrementStatement property értékét a harmadik paraméter állítja be. A megadott utasítás gondoskodik a ciklusváltozó növeléséről.
  new CodeAssignStatement(new CodeVariableReferenceExpression("i"), new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1) )),
A negyedik paraméter egy utasítás tömb, melyben megadhatjuk, hogy milyen utasítások hajtódjanak végre a ciklusban. Ide többek között el kell helyeznünk a múlt részben már megismert feltételes elágazásokat generáló objektumokat.
  new CodeStatement[] {new CodeSnippetStatement("act = Convert.ToInt32(param[i]);"),ifokstat,ifnotokstat});
A TRY-CATCH blokkot reprezentáló objektum Statement kollekciójában így most már csak a FOR ciklust generáló objektumot kell elhelyezni.
trycatch.TryStatements.Add(forloop);

Futásidejű kódgenerálás cikksorozat