1 /*
   2  * This will be a test to see whether calling JavaScript functions from AEC
   3  * works as expected. It will also attempt to expose as many potential compiler
   4  * bugs as possible by implementing the permutations algorithm.
   5  */
   6 
   7 // So, those are JavaScript functions which I am planning to call from AEC:
   8 Function printInt(Integer32 int) Which Returns Nothing Is External;
   9 Function printString(PointerToCharacter ptr) Which Returns Nothing Is External;
  10 Function clearScreen() Which Returns Nothing Is External;
  11 
  12 // JavaScript equivalent of C "strlen" is the "length" property of a string
  13 // and there is, as far as I know, no way to call it from outside of JS.
  14 // Nevertheless, I think I can easily write it myself.
  15 Function strlen(PointerToCharacter ptr) Which Returns Integer32
  16     Does { // The curly brace '{' here is not necessary, it is just here so that
  17            // ClangFormat knows how to format the code, and the tokenizer
  18            // ignores it.
  19   Return ValueAt(ptr) = 0 ? 0 : 1 + strlen(ptr + 1);
  20 }
  21 EndFunction; // The semi-colon after "EndFunction" is not necessary either, it
  22              // is a signal to ClangFormat.
  23 
  24 Integer32 originalNumberOfDigits[10], NDEBUG : = 1, numberOfPermutations;
  25 
  26 Function recursiveProcedure(
  27     PointerToCharacter currentAttempt) Which Returns Nothing Does {
  28   Integer32 lengthOfTheCurrentAttempt : = strlen(currentAttempt);
  29   If not(NDEBUG) Then {
  30     printString(
  31         "DEBUG: \"recursiveProcedure\" has been invoked with the argument: \"");
  32     printString(currentAttempt);
  33     printString("\". \"strlen\" says it has length of ");
  34     printInt(lengthOfTheCurrentAttempt);
  35     printString(".\n");
  36   }
  37   EndIf;
  38   Integer32 currentNumberOfDigits[10] : = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  39                                       i : = 0;
  40   While i < lengthOfTheCurrentAttempt Loop {
  41     currentNumberOfDigits[ValueAt(currentAttempt + i) - '0'] += 1;
  42     i += 1;
  43   }
  44   EndWhile;
  45   If not(NDEBUG) Then {
  46   i:
  47     = 0;
  48     While i < 10 Loop {
  49       printString("DEBUG: The current number has ");
  50       printInt(currentNumberOfDigits[i]);
  51       printString(" digits '");
  52       printInt(i);
  53       printString("'.\n");
  54       i += 1;
  55     }
  56     EndWhile;
  57   }
  58   EndIf;
  59 i:
  60   = 0;
  61   While i < 10 Loop {
  62     If currentNumberOfDigits[i] > originalNumberOfDigits[i] Then {
  63       If not(NDEBUG) Then {
  64         printString("DEBUG: There are too many digits '");
  65         printInt(i);
  66         printString("', ending \"recursiveProcedure\".\n");
  67       }
  68       EndIf;
  69       Return;
  70     }
  71     EndIf;
  72     i += 1;
  73   }
  74   EndWhile;
  75   Integer32 haveWeFoundAPermutation : = 1;
  76 i:
  77   = 0;
  78   While i < 10 Loop {
  79     If currentNumberOfDigits[i] < originalNumberOfDigits[i] Then {
  80     haveWeFoundAPermutation:
  81       = 0;
  82     }
  83     EndIf;
  84     i += 1;
  85   }
  86   EndWhile;
  87   If haveWeFoundAPermutation Then {
  88     printString("Permutation #");
  89     numberOfPermutations += 1;
  90     printInt(numberOfPermutations);
  91     printString(": ");
  92     printString(currentAttempt);
  93     printString("\n");
  94     Return;
  95   }
  96   EndIf;
  97   Character digitWeAreAdding : = '0';
  98   While digitWeAreAdding < '9' + 1 Loop { // The less-than-or-equal operator
  99                                           //"=<" hasn't yet been implemented.
 100     Character newAttempt[12];
 101   i:
 102     = 0;
 103     While i < 12 Loop {
 104       If i < lengthOfTheCurrentAttempt Then {
 105         newAttempt[i] : = ValueAt(currentAttempt + i);
 106       }
 107       Else { newAttempt[i] : = 0; }
 108       EndIf;
 109       i += 1;
 110     }
 111     EndWhile;
 112     newAttempt[lengthOfTheCurrentAttempt] : = digitWeAreAdding;
 113     If currentNumberOfDigits[digitWeAreAdding - '0'] <
 114         originalNumberOfDigits[digitWeAreAdding - '0'] Then { // To speed
 115                                                               // things up
 116                                                               // a bit.
 117       recursiveProcedure(AddressOf(newAttempt[0]));
 118     }
 119     EndIf;
 120     digitWeAreAdding += 1;
 121   }
 122   EndWhile;
 123 }
 124 EndFunction;
 125 
 126 Function
 127 printPermutationsOfDigits(Integer32 original) Which Returns Nothing Does {
 128   clearScreen();
 129   If original < 0 Then { original *= -1; }
 130   EndIf;
 131   printString("Printing all the permutations of digits of the number: ");
 132   printInt(original); // Unfortunately, the JavaScript standard library
 133                       // doesn't have "printf".
 134   printString("\n");
 135   Integer32 i : = 0;
 136   While i < 10 Loop {
 137     originalNumberOfDigits[i] : = 0;
 138     i += 1;
 139   }
 140   EndWhile;
 141   If original = 0 Then { originalNumberOfDigits[0] : = 1; }
 142   EndIf;
 143   While original > 0 Loop {
 144     originalNumberOfDigits[mod(original, 10)] += 1;
 145     original /= 10;
 146   }
 147   EndWhile;
 148   If not(NDEBUG) Then {
 149   i:
 150     = 0;
 151     While i < 10 Loop {
 152       printString("DEBUG: The original number has ");
 153       printInt(originalNumberOfDigits[i]);
 154       printString(" digits '");
 155       printInt(i);
 156       printString("'.\n");
 157       i += 1;
 158     }
 159     EndWhile;
 160   }
 161   EndIf;
 162 numberOfPermutations:
 163   = 0;
 164   recursiveProcedure("");
 165   printString("The end!");
 166 }
 167 EndFunction;
 168