التطبيع داخل الممثّلات


لكي يكون للحلول ذات الاختلافات غير الجوهرية التمثيل نفسه، ينبغي لأداة التمثيل أن تطبّق عمليات التطبيع. وبشكل عام، تبدو عملية إنشاء تمثيل مطبَّع هكذا:

  • حلّل الكود في الحل إلى شجرة الصياغة المجردة (AST)
  • طبّق عمليات التطبيع على شجرة الصياغة المجردة
  • حوّل شجرة الصياغة المجردة المطبَّعة إلى سلسلة نصية
  • اكتب سلسلة شجرة الصياغة المجردة المطبَّعة في ملف باسم representation.txt (انظر الواجهة)

لاحظ مع ذلك أن التمثيل ليس بالضرورة شجرة صياغة مجردة، بل قد يكون كودًا عاديًا (مطبَّعًا)، فأيّهما كان الأنسب لمسارك.

لمساعدتك على البدء، سنعرض الآن بعض استراتيجيات التطبيع الشائعة.

ملاحظة 1: أمثلة التطبيع لا تُبنى على بعضها، بل تعرض كل منها عملية تطبيع واحدة بعينها. أما أداة التمثيل الحقيقية فستريد تطبيقها تباعًا.

ملاحظة 2: الكود في هذه الإرشادات مكتوب بلغة C#، لكن الإرشادات نفسها لا ترتبط بلغة بعينها.

تطبيع المعرّفات

لكي لا يعتمد التمثيل على الأسماء، يمكن استبدال الأسماء التي يعرّفها المستخدم (مثل المتغيرات والدوال وغيرها) بعناصر نائبة. في هذه الحالة، ينبغي إنتاج ملف mapping.json (انظر الواجهة).

من المهم ملاحظة أنه يجب استبدال كل الأسماء المتطابقة بالعنصر النائب نفسه، بصرف النظر عن النطاق.

الكود المصدري

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

التمثيل

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

تطبيع المسافات البيضاء

المسافات البيضاء غير المتسقة شائعة إلى حد أن تطبيعها صار خطوة تطبيع معتادة. وينبغي كذلك تطبيع نهايات الأسطر.

الكود المصدري

using   System;

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

التمثيل

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

تطبيع الكتل

في لغات كثيرة، يملك المستخدم قدرًا من الحرية في كيفية تعريف كتلة (أو نطاق). مثلًا، في معظم اللغات الشبيهة بلغة C، يُعلَن النطاق بين الأقواس المعقوفة. وكثيرًا ما لا يهم إن وضعتها في السطر نفسه أم في السطر التالي، لذا يمكن تطبيع ذلك.

الكود المصدري

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

        return 1;
    }
}

التمثيل

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

        return 1;
    }
}

إزالة الكود غير المؤثر

ليست كل أجزاء الكود ذات أهمية لأداة التمثيل، لذا يمكن إزالتها. على سبيل المثال، في معظم اللغات تكون التعليقات غير مؤثرة ويمكن حذفها بأمان.

الكود المصدري

/*
   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
    }
}

التمثيل

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

تطبيع الترتيب حين لا يكون مؤثرًا

في بعض الحالات لا يهم ترتيب الكود. ولمنع الكود نفسه، إذا ورد بترتيب مختلف، من إنتاج تمثيلات مختلفة، قد يفيد ترتيبه. وعادةً ما تكون العناصر المطلوب ترتيبها دوال أو تعريفات. وقد يكون العثور على المعيار أو المعايير التي يُرتَّب بها أمرًا صعبًا، وكذلك تنفيذها. ويمكن أن يكون أحد المعايير عدد العقد الفرعية التي تحويها العقدة في شجرة الصياغة المجردة، وآخر اسم نوع العقدة الفرعية الأولى.

يرتّب هذا المثال حسب نوعٍ ما من طول الدالة:

الكود المصدري

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

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

التمثيل

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

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