Normalizálás a representereken belül


Ahhoz, hogy a lényegtelen eltéréseket mutató megoldások reprezentációja ugyanaz legyen, a representernek normalizálásokat kell alkalmaznia. A normalizált reprezentáció létrehozásának folyamata általában így néz ki:

  • A megoldás kódját alakítsd absztrakt szintaxisfává (AST)
  • Alkalmazd a normalizálásokat az AST-ra
  • A normalizált AST-t alakítsd stringgé
  • Írd ki a normalizált AST stringjét egy representation.txt nevű fájlba (lásd az interfészt)

Megjegyzendő azonban, hogy a reprezentációnak nem kell AST-nak lennie: lehet sima (normalizált) kód is, attól függően, hogy mi működik a legjobban a kurzusod számára.

Hogy segítsünk az indulásban, most bemutatunk néhány gyakori normalizálási stratégiát.

  1. megjegyzés: a normalizálási példák nem épülnek egymásra, mindegyik csak egy-egy konkrét normalizálást mutat be. Egy valódi representer ezeket egymás után alkalmazná.

  2. megjegyzés: az útmutatóban szereplő kód C#-ban lesz, de maga az útmutató nyelvfüggetlen.

Azonosítók normalizálása

Ahhoz, hogy a reprezentációk függetlenek legyenek az elnevezésektől, a felhasználó által definiált neveket (például változók, függvények stb.) helyőrzőkkel lehet helyettesíteni. Ebben az esetben létre kell hozni egy mapping.json fájlt (lásd az interfészt).

Fontos megjegyezni, hogy minden azonos nevet ugyanazzal a helyőrzővel kell helyettesíteni, függetlenül a scope-tól.

Forráskód

public static class Fake
{
    public static int Test(int input)
    {
        var test = input + 2;
        return test;
    }
}

Reprezentáció

public static class PLACEHOLDER_1
{
    public static int PLACEHOLDER_2(int PLACEHOLDER_3)
    {
        var PLACEHOLDER_4 = PLACEHOLDER_3 + 2;
        return PLACEHOLDER_4;
    }
}

Szóközök normalizálása

A következetlen szóközhasználat olyan gyakori, hogy a normalizálása az egyik leggyakoribb normalizálási lépés. A sorvégeket is normalizálni kell.

Forráskód

using   System;

     public static    class Fake
{
    public     static   DateTime Add    (DateTime    birthDate)
    {
        return birthDate.Add( TimeSpan.FromSeconds   (   10  ) )   ;
    }
}

Reprezentáció

public static class Fake
{
    public static DateTime Add(DateTime birthDate)
    {
        return birthDate.Add(TimeSpan.FromSeconds(10));
    }
}

Blokkok normalizálása

Sok nyelvben a felhasználónak bizonyos szabadsága van abban, hogyan definiál egy blokkot (vagy scope-ot). Például a legtöbb C-szerű nyelvben a scope-ot kapcsos zárójelek közé zárjuk. Általában nem számít, hogy ugyanabba a sorba teszed-e őket vagy a következőbe, ezért ezt normalizálni lehet.

Forráskód

public static class Fake {
    public static int Test() {
        if (1 > 2) {
            return 0;
        }

        return 1;
    }
}

Reprezentáció

public static class Fake
{
    public static int Test()
    {
        if (1 > 2)
        {
            return 0;
        }

        return 1;
    }
}

A lényegtelen kód eltávolítása

Nem a kód minden része lényeges a representer számára, így azok eltávolíthatók. Például a legtöbb nyelvben a megjegyzések lényegtelenek, és nyugodtan eltávolíthatók.

Forráskód

/*
   These are some very nice
   comments spanning multiple lines
*/
public static class Fake
{
    // Nice method
    public static string Test()
    {
        return "Test"; // This is very nice
    }
}

Reprezentáció

public static class Fake
{
    public static string Test()
    {
        return "Test";
    }
}

A sorrend normalizálása, ahol nem számít

Bizonyos esetekben a kód sorrendje nem számít. Hogy megakadályozzuk, hogy ugyanaz a kód más sorrendben más reprezentációt hozzon létre, érdemes lehet rendezni. Általában a rendezendő elemek függvények vagy deklarációk. Trükkös lehet megtalálni, hogy mi alapján rendezz, és a megvalósítása is trükkös lehet. Az egyik szempont lehet, hogy hány AST-csomópont gyermeke van az adott csomópontnak, a másik pedig az első gyermekcsomópont típusának a neve.

Ez a példa valamilyen függvényhossz szerint rendez:

Forráskód

public static class Fake
{
    public static string Test2()
    {
        int a = "Test2";
        return a;
    }

    public static string Test()
    {
        return "Test";
    }
}

Reprezentáció

public static class Fake
{
    public static string Test()
    {
        return "Test";
    }

    public static string Test2()
    {
        int a = "Test2";
        return a;
    }
}