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