Skip to content

Latest commit

 

History

History
172 lines (126 loc) · 4.49 KB

livebook_examples.livemd

File metadata and controls

172 lines (126 loc) · 4.49 KB

CobolToElixir

Installing CobolToElixir

COBOL is not technically necessary to run CobolToElixir, but the examples below do use it to verify expected output. You can install it with brew install gnu-cobol (this may take a while, run outside of Livebook instead to see progress).

{_, 0} = System.cmd("brew", ["install", "gnu-cobol"], stderr_to_stdout: true)

Verify it installed correctly by running the COBOL Compiler cobc:

{"GnuCOBOL" <> _, 0} = System.cmd("cobc", ["-h"], stderr_to_stdout: true)

Next, add :cobol_to_elixir. In a project, add this line to your dependencies:

{:cobol_to_elixir, "~> 0.0.0"}

In this Livebook, we can install using Mix.install

:ok =
  Mix.install([
    {:cobol_to_elixir,
     git: "[email protected]:TheFirstAvenger/cobol_to_elixir.git",
     ref: "dc082c1e22ed06019fa1da777f53658cf81f0b3b"}
  ])

Convert a simple COBOL program

Lets start with a simple COBOL program to Elixir. This program has one variable set, and displays that variable:

cobol = """
       >>SOURCE FORMAT FREE
IDENTIFICATION DIVISION.
PROGRAM-ID. Livebook1.
AUTHOR. Mike Binns.
DATE-WRITTEN. June 25th 2021
DATA DIVISION.
WORKING-STORAGE SECTION.
01 Name     PIC X(4) VALUE "Mike".
PROCEDURE DIVISION.

DISPLAY "Hello " Name

STOP RUN.
"""

Now, lets validate that this is correct COBOL by compiling and then executing it using CobolToElixir.Util.execute_cobol_code!/2

%{output: "Hello Mike\n"} = CobolToElixir.Util.execute_cobol_code!(cobol)

Next, let's use CobolToElixir.convert() to convert the COBOL code to Elixir:

elixir_code = CobolToElixir.convert!(cobol)
IO.puts(elixir_code)

There is a bunch of boilerplate helper functions, but notice that the Module is named ElixirFromCobol.Livebook1, the author and date written are added to the @moduledoc, and that the do_main function contains the Elixir version of our COBOL working storage section and procedure division:

defmodule ElixirFromCobol.Livebook1 do
  @moduledoc """
  author: Mike Binns
  date written: June 25th 2021
  """

  ...

  def do_main do
    # pic: XXXX
    var_Name = "Mike"
    pics = %{"Name" => {:str, "XXXX", 4}}
    IO.puts "Hello " <> var_Name
    throw :stop_run
  end

Next, lets try running that Elixir code. We will define a local function to compile the give Elixir code, load it into memory, run the main function, and then unload the code from memory. We will then run that function with the Elixir code output from our CobolToElixir transpiler.

execute_elixir = fn elixir_code, module ->
  Code.compile_string(elixir_code)
  {:module, ^module} = Code.ensure_loaded(module)

  apply(module, :main, [])

  true = :code.delete(module)
  :code.purge(module)
  :ok
end

execute_elixir.(elixir_code, ElixirFromCobol.Livebook1)

Note that there was a compiler warning because we defined pics but did not use it. More advanced code conversions will use this variable.

Also notice that Hello Mike appears in the logs.

Additional Examples - Paragraphs

COBOL uses "paragraphs", which are similar to functions, but not exactly the same. Below we can see how a more complex COBOL program, with multiple paragraphs calling into each other, is converted to Elixir.

First, lets define the Cobol code

cobol = """
       >>SOURCE FORMAT FREE
IDENTIFICATION DIVISION.
PROGRAM-ID. proceduretest.
AUTHOR. Mike Binns.
DATE-WRITTEN.March 19th 2021.
PROCEDURE DIVISION.
SubOne.
  DISPLAY "In Paragraph 1"
  PERFORM SubTwo
  DISPLAY "Returned to Paragraph 1"
  PERFORM SubFour 2 TIMES.
  STOP RUN.

SubThree.
  DISPLAY "In Paragraph 3".

SubTwo.
  DISPLAY "In Paragraph 2"
  PERFORM SubThree
  DISPLAY "Returned to Paragraph 2".

SubFour.
  DISPLAY "Repeat".

STOP RUN.

"""

Next, we execute that COBOL code to verify it is valid, and to determine the expected output

%{output: cobol_output} = CobolToElixir.Util.execute_cobol_code!(cobol)
IO.puts(cobol_output)

Now, lets convert that COBOL to Elixir. Note the contents of the do_main function, and the other functions that were created to mirror the paragraphs.

elixir_code = CobolToElixir.convert!(cobol)
IO.puts(elixir_code)

And finally, run that Elixir code and see that the output is the same as the COBOL output

IO.puts("Elixir output:")
execute_elixir.(elixir_code, ElixirFromCobol.Proceduretest)
IO.puts("Cobol output:")
IO.puts(cobol_output)