B Compiler tutorial

Introduction

This tutorial is about developping software that embed the B Compiler library, ranging from metrics computation tool to code generator.

Ready for developping with B Compiler Library

The easiest way to proceed is to develop software in the directory that hosts the B Compiler. There are few steps to follow in order to be ready for developping with the B Compiler Library:

  • create a new directory (for example: MyExample)
  • edit the CMakeLists.txt file. It should read like:
project(bcomp)

cmake_minimum_required(VERSION 2.4)

add_subdirectory(STUB_DECOMPILER)
add_subdirectory(RESOURCES)
add_subdirectory(B_COMPILER)
add_subdirectory(FIND_SPEC)

Add the following line:

add_subdirectory(MyExample)
  • in the MyExample directory, create the CMakeLists.txt file and copy the following in it:
project(MyExample)

include_directories(${BCOMP_SOURCE_DIR}
	${DECOMP_SOURCE_DIR}
	${RESOURCES_SOURCE_DIR}
)

add_executable(MyExample MyExample.cpp)
target_link_libraries(MyExample BCOMP STUB_DECOMP RES)
  • in the MyExample directory, create the MyExample.cpp file and copy the following in it:
#include <c_port.h>
#include <c_api.h>
#include <c_path.h>
#include <iostream> 

using namespace std;
int function main(int argc, char* argv[]) {
	const string filename=argv[1];

	cout << "Reading file: " << argv[1] << endl;
	T_betree *betree= compiler_syntax_analysis(filename.c_str());
}

To generate MyExample application:

  • go to the directory that hosts the B Compiler (the one that contains the ReadMe.txt file).
  • execute the command:
cmake -G "MinGW Makefiles"

You should get the following messages

-- Configuring done
-- Generating done
-- Build files have been written to: D:/DEV/TOOLS/bcomp
  • execute the command:
make

You should get the following messages

[  0%] Built target STUB_DECOMP
[  8%] Built target RES
[ 97%] Built target BCOMP
[ 98%] Built target BCOMP_EXE
[ 99%] Built target find_spec
Scanning dependencies of target MyExample
[100%] Building CXX object MyExample/CMakeFiles/MyExample.dir/MyExample.obj
Linking CXX executable MyExample.exe
[100%] Built target MyExample

The MyExample executable file is located in the MyExample directory. MyExample requires one parameter that is the name of a B model which will be syntactly analyzed. If nothing is displayed then the B model is correct.

Navigating operations

Once a betree has been successfully built from a B model, it is possible to navigate it. In this section, navigation among operations is presented.

In the previous example, a betree is constructed when the function compiler_syntax_analysis is called. From that betree, we would like to get a reference to the top level machine:

     T_machine *mch = betree->get_root();

This machine is then used to navigate operations:

     T_op* operation=mch->get_operations();
     while (operation != NULL) {
           string op_name=operation->get_op_name()->get_value();
           cout << "Operation name : " << op_name << endl;
           operation = (T_op*)operation->get_next(); 	
     }

The resulting MyExample.cpp file is then compiled successfully.

Applied on the M1.mch model

MyExampleMyExample.exe M1.mch

the following messages are displayed:

Reading file: M1.mch
Operation name : OP1
Operation name : OP2

Navigating substitutions

In this section, navigation among substitutions is presented.

In the previous example, operations are browsed sequentiall, through the get_next() function.

This operation is used to navigate substitutions:

         T_substitution* subst=operation->get_body();
         T_item* it_subst=(T_item*) subst;
         cout << "  Substitution: ";
         while (it_subst!=NULL) {
               cout << it_subst->get_class_name();
               it_subst=it_subst->get_next();
         }
         cout << endl;

The execution of MyExample on M1.mch leads to the following messages:

Reading file: M1.mch
Operation name : OP1
  Substitution: T_begin
Operation name : OP2
  Substitution: T_select

The complete MyExample.cpp file is listed below:

#include <c_port.h>
#include <c_api.h>
#include <c_path.h>
#include <iostream> 

using namespace std;
int function main(int argc, char* argv[]) {
    const string filename=argv[1]; 

    cout << "Reading file: " << argv[1] << endl;
    T_betree *betree= compiler_syntax_analysis(filename.c_str());
    T_machine *mch = betree->get_root(); 

    T_op* operation=mch->get_operations();
    while (operation != NULL) {
          string op_name=operation->get_op_name()->get_value();
          cout << "Operation name : " << op_name << endl;

          T_substitution* subst=operation->get_body();
          T_item* it_subst=(T_item*) subst;
          cout << "  Substitution: ";
          while (it_subst!=NULL) {
                cout << it_subst->get_class_name();
                it_subst=it_subst->get_next();
          }
          cout << endl;
          operation = (T_op*)operation->get_next();
      }
}