This article's goal is to explain how the GraalVM could be running CoBOL on pretty much any platform. IT departments, mainly in financial institutions and governments are desperately seeking CoBOL and mainframe experts but the lack of training course and the repelling Z/OS TSO environment are not encouraging vocations. Another major issue with those technologies resides in the costs of mainframe licenses. I think, hope, both could be solved developing CoBOL in modern environments. In case you don't know, rewriting the code and just shutting down the mainframes is not an option, see this great article.
Using Flex and Bison for lexical parsing, GnuCOBOL can transpile CoBOL to C. It can
directly compile CoBOL using your platform toolchain but it is not our goal here, as we want to
execute it with GraalVM. There are many CoBOL compilers out there. This one implement major part
of CoBOL 1985, 2002 and several extensions of other compilers. This compiler and it's dependency
libcob can easily be installed using synaptic package manager command
open-cobol. Open CoBOL is the former name of GnuCOBOL, it can be checked that way:
chrichri@chrichri-debian:~$ cobc -version cobc (GnuCOBOL) 2.2.0 Copyright (C) 2017 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Edward Hart Built Jul 17 2018 20:29:40 Packaged Sep 06 2017 18:48:43 UTC C version "7.3.0"
If not already installed, GraalVM installation
is described on their website. Executing native code require a GraalVM package call llvm-toolchain.
On my system I already have
lli so I created symlinks
lli-gu. I prefer to create a symlink with a different name for
lli executables rather that extending the path which will
required the use of
update-alternatives. A great medium post from
an Oracle collaborator detail the GraalVM llvm-toolchain.
Let use the Mandelbrot set implemented in CoBOL in our example, see
identification division. program-id. MandelbrotSet. data division. working-storage section. 01 ResolutionX constant 240. 01 ResolutionY constant 100. 01 RealPlaneMin constant -2.5. 01 RealPlaneMax constant 0.8. 01 ImaginaryPlaneMin constant -1.25. 01 ImaginaryPlaneMax constant 1.25. 01 ProportionalX pic S99V9(16) usage comp-5 value zeros. 01 ProportionalY pic S99V9(16) usage comp-5 value zeros. 01 IterationsMax constant 60. 01 Threshold constant 10000. 01 ScreenX pic 999 usage comp-5. 01 ScreenY pic 999 usage comp-5. 01 MathPlaneX pic S99V9(16) usage comp-5. 01 MathPlaneY pic S99V9(16) usage comp-5. 01 PointX pic S9(7)V9(8) usage comp-5. 01 PointY pic S9(7)V9(8) usage comp-5. 01 XSquared pic S9(10)V9(8) usage comp-5. 01 YSquared pic S9(10)V9(8) usage comp-5. 01 Iteration pic 999 value zero. 01 TempVar pic S9(5)V9(8) usage comp-5. procedure division. compute ProportionalX = (RealPlaneMax - RealPlaneMin) / (ResolutionX - 1) compute ProportionalY = (ImaginaryPlaneMax - ImaginaryPlaneMin) / (ResolutionY - 1) perform varying ScreenY from 0 by 1 until ScreenY is equal to ResolutionY compute MathPlaneY = ImaginaryPlaneMin + (ProportionalY * ScreenY) perform varying ScreenX from 0 by 1 until ScreenX is equal to ResolutionX compute MathPlaneX = RealPlaneMin + (ProportionalX * ScreenX) move zero to PointX move zero to PointY multiply PointX by PointX giving XSquared multiply PointY by PointY giving YSquared perform with test after varying Iteration from 0 by 1 until Iteration >= IterationsMax or XSquared + YSquared >= Threshold compute TempVar = XSquared - YSquared + MathPlaneX compute PointY = 2 * PointX * PointY + MathPlaneY move TempVar to PointX compute XSquared = PointX * PointX compute YSquared = PointY * PointY end-perform if Iteration is equal to IterationsMax display "*" with no advancing else display " " with no advancing end-if end-perform display " " end-perform stop run. end program MandelbrotSet.
Using GnuCOBOL, the C intermediate can be produced with the following command:
cobc -C -x mandelbrot.cob
The project should look like:
. ├── mandelbrot.c ├── mandelbrot.c.h ├── mandelbrot.c.l.h └── mandelbrot.cob
One point not completely clear from their documentation, is the difference with the regular Clang.
On contrary to regular Clang, Graal one compile directly to LLVM bytecode without
Do not mix regular LLVM toolchain with GraalVM toolchain in general.
Don't forget to include the
libcob dependency with
-lcob, our compiling
clang-gu mandelbrot.c -o bin/mandelbrot-graal.bc -lcob
The project should look like:
. ├── bin │ └── mandelbrot-graal.bc ├── mandelbrot.c ├── mandelbrot.c.h ├── mandelbrot.c.l.h └── mandelbrot.cob
The LLVM interpreter
Christophe Brun, https://www.papit.fr/