APL compiler written in Standard ML
Standard ML APL C++
Switch branches/tags
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
tests
.gitignore
AplCompile.sml
MIT_LICENSE.md
Makefile
README.md
aplc.mlb
aplc.sml
aplcompile.mlb
aplcompile.smackspec
comp.md
coverage.md
preamble.apl

README.md

aplcompile: An APL Compiler in Standard ML

This software implements an APL compiler in Standard ML.

See the compilation scheme.

See also the coverage page.

An example

Here is the result of compiling and running the following program:

f  {5+}     Function adding 5 to its argument (⍵)
+/ f  30     Apply f to the vector 1..30 and
               sum up the elements in the resulting vector

Here is what happens when the program is compiled and executed:

bash-3.2$ ./aplc tests/test.apl 
Reading file: tests/test.apl
Parse success:
 [Assign(f,Lam[0,1](App2(Add,5,Omega))),App1(AppOpr1[1](Slash,Add),App1(f,App1(Iota,30)))]
Evaluating
double kernel(int n1) {
  int n0 = 0;
  for (int n9 = 0; n9 < 30; n9++) {
    n0 = ((6+n0)+n9);
  }
  return i2d(n0);
}
Result is 615.0

Another example

Consider the program

diff  {1¯1}
signal  {¯505050×(diff 0,)÷0.01+}
+/ signal  100

Here is the result of compiling it:

bash-3.2$ ./aplc tests/signal.apl 
Reading file: tests/signal.apl
Parse success:
 [Assign(diff,Lam[0,1](App2(Drop,1,App2(Sub,Omega,App2(Rot,-1,Omega))))),
  Assign(signal,Lam[0,1](App2(Max,-50,App2(Min,50,App2(Times,50,App2(Div,App1(diff,App2(Cat,0,Omega)),App2(Add,0.01,Omega))))))),
  App1(AppOpr1[1](Slash,Add),App1(signal,App1(Iota,100)))]
Evaluating
double kernel(int n11) {
  double d10 = 0.0;
  for (int n59 = 0; n59 < 100; n59++) {
    d10 = (max(-50.0,min(50.0,(50.0*(i2d(((1+n59)-((n59<1) ? 0 : n59)))
          / (0.01+i2d((1+n59)))))))+d10);
  }
  return d10;
}
Result is 258.557340366

Example demonstrating transpose and a double-reduce

Consider the following APL program:

a  3 2   5
a2  3 2   4
b   a
c  b,  a2
×/ +/ c

 1 2  1 3 5  -+-> 9  
 3 4  2 4 1  -+-> 7
 5 1 
      1 3 1  -+-> 5
      2 4 2  -+-> 8
                 ---
                 2520

Here is the result of compiling it:

bash-3.2$ ./aplc tests/test15.apl
Reading file: tests/test15.apl
Parse success:
 [Assign(a,App2(Rho,Vec[3,2],App1(Iota,5))),
  Assign(a2,App2(Rho,Vec[3,2],App1(Iota,4))),
  Assign(b,App1(Trans,a)),
  Assign(c,App2(Cat,b,App1(Trans,a2))),
  App1(AppOpr1[1](Slash,Times),App1(AppOpr1[1](Slash,Add),c))]
Evaluating
double kernel(int n17) {
  int n16 = 1;
  for (int n89 = 0; n89 < 4; n89++) {
    int n39 = 0;
    for (int n92 = 0; n92 < min(3,max((12-(n89*3)),0)); n92++) {
      n39 = ((((n92+(n89*3))<6) ? (((((n92+(n89*3))==5) ? (n92+(n89*3)) : 
            ((2*(n92+(n89*3)))%5))%5)+1) : ((((((n92+(n89*3))-6)==5) ? ((n92+(n89*3))-6) : 
            ((2*((n92+(n89*3))-6))%5))%4)+1))+n39);
    }
    n16 = (n39*n16);
  }
  return i2d(n16);
}
Result is 2520.0

Example demonstrating matrix-multiplication

a  3 2   5
b   a
c  a +.× b
×/ +/ c

       1  3  5
       2  4  1

 1 2   5 11  7  -+->    23
 3 4  11 25 19  -+->    55
 5 1   7 19 26  -+->    52
                     65780

Here is the result of compiling the example:

bash-3.2$ ./aplc tests/test13.apl 
Reading file: tests/test13.apl
Parse success:
 [Assign(a,App2(Rho,Vec[3,2],App1(Iota,5))),
  Assign(b,App1(Trans,a)),
  Assign(c,App2(AppOpr2[2](Dot,Add,Times),a,b)),
  App1(AppOpr1[1](Slash,Times),App1(AppOpr1[1](Slash,Add),c))]
Evaluating
double kernel(int n8) {
  int n7 = 1;
  for (int n180 = 0; n180 < 3; n180++) {
    int n26 = 0;
    for (int n192 = 0; n192 < min(3,max((9-(n180*3)),0)); n192++) {
      int n53 = 0;
      for (int n195 = 0; n195 < min(min(2,max((6-(((n192+(n180*3))/3)*2)),0)),min(2,max((6-(((n192+(n180*3))%3)*2)),0))); n195++) {
        n53 = (((((n195+(((n192+(n180*3))/3)*2))%5)+1)*(((((((n195+(((n192+(n180*3))%3)*2))==5) 
              ? (n195+(((n192+(n180*3))%3)*2)) : ((3*(n195+(((n192+(n180*3))%3)*2)))%5))==5) 
              ? (((n195+(((n192+(n180*3))%3)*2))==5) 
              ? (n195+(((n192+(n180*3))%3)*2)) : ((3*(n195+(((n192+(n180*3))%3)*2)))%5)) 
              : ((2*(((n195+(((n192+(n180*3))%3)*2))==5) 
              ? (n195+(((n192+(n180*3))%3)*2)) 
              : ((3*(n195+(((n192+(n180*3))%3)*2)))%5)))%5))%5)+1))+n53);
      }
      n26 = (n53+n26);
    }
    n7 = (n26*n7);
  }
  return i2d(n7);
}
Result is 65780.0

Try it!

The software makes use of the smlunicode library project for lexing, the aplparse project for parsing, and the MoA project for implementing the fundamental APL array operations. This means that you need to checkout the smlunicode sources, the aplparse sources, and the MoA sources in folders next to the aplcompile sources.

You also need a Standard ML compiler (e.g., Mlton).

Then simply write make aplc followed by ./aplc in your shell.

To run a series of tests, execute make tests in your shell.

Limitations

Todo: Improved error handling.

See also the coverage page.

License

This software is published under the MIT License.