The generic compilation component: a tree interpreter

The program
The Input
Setting up the environment
The command file
The Output

The purpose of this assignment is to become familiar with the organization of the GNAT front-end, and to experiment with a tree-walking procedure, which provides a skeleton for the code generator that is part of the course project. For this assignment, you should compile the required pieces of the front-end and the tree-walker program, and then modify this program to identify the expressions it contains, and print them in prefix notation.

The following Sample tree-walking routine traverses the tree created by the front-end, and identifies some of the components of the program. In this case, it lists the kind of all nodes traversed, and the names of the subprograms declared in the visible part of package declarations, both for the main unit and for the units that appear in its context clause. ('withed' units).
The program
with Ada.Command_Line; use Ada.Command_Line;
with Atree; use Atree;
with GNAT.OS_Lib; use GNAT.OS_Lib;
with GNAT.Io;
with Lib;
with Nlists; use Nlists;
with Sinfo; use Sinfo;
with Sinput;
with Namet; use Namet;
with Tree_In;
with Types; use Types;

procedure Test_Walker is
   N              : Node_Id;
   Tree_File_Name : String    := Argument (1) & Ascii.Nul;
   Error_Msg      : String    := " had unhandled exception"
                                  & Ascii.LF & Ascii.Nul;
   Result         : Integer;
   FD             : File_Descriptor;
   procedure Walk (N : Node_Id);
   --  Recursive procedure that does the work.
   procedure Walk (N : Node_Id) is
      Line       : Integer;
      Loc        : Source_Ptr;
      Kind       : Node_Kind;
      Kids       : List_Id;
      L          : Node_Id;
      F          : Node_Id;

      Kind := Nkind (N);
      Gnat.IO.Put ("Encountered Node Kind : ");
      Gnat.IO.Put_Line (Node_Kind'Image (Kind));

      case Kind is
	 when N_Compilation_Unit =>
	    Walk (Unit (N));
	    Kids := Context_Items (N);        --  list of withed units
	    L := First (Kids);

	    while L /= Empty loop
	       Walk (L);
	       L := Next (L);
	    end loop;

	 when N_With_Clause =>
	    Walk (Library_Unit(N));

	 when N_Package_Declaration =>
	    Walk (Specification (N));

	 when N_Package_Specification =>
	    Kids := Visible_Declarations (N);
	    L := First (Kids);

	    while L /= Empty loop
	       Walk (L);
	       L := Next (L);
	    end loop;

	 when N_Subprogram_Declaration =>
 	       Subprog_Id : Node_Id := Defining_Unit_Name (Specification (N));
	       Subprog_Name_Id : Name_Id := Chars (Subprog_Id);
	       Loc := Sloc (Subprog_Id);
	       Line := Integer (Sinput.Get_Line_Number (Loc));
	       Get_Name_String (Chars (Subprog_Id));
	       Gnat.IO.Put ("Declaration of ");
	       Gnat.IO.Put (Name_Buffer (1 .. Name_Len));
	       Gnat.IO.Put (" found on Line ");
	       Gnat.IO.Put (Line);

	 when others =>
      end case;
   end Walk;


   FD := Open_Read (Tree_File_Name'Address, Binary);
   Tree_In (FD);
   N := Lib.Cunit (Types.Main_Unit);
   Walk (N);

   when others =>
      Result := GNAT.OS_Lib.Write (Standerr, Tree_File_Name'Address,
				   Tree_File_Name'Length - 1);
      Result := GNAT.OS_Lib.Write (Standerr, Error_Msg'Address,
				   Error_Msg'Length - 1);
end Test_Walker;

test program for tree walker

package Tiny is I: Integer; procedure Foo (J : Integer); procedure Bar; end Tiny;

Setting Up the environment

The GNAT compiler is accessible on the all NYU servers on which MS students have accounts. The system and all documentation can be found under /usr/local/pkg/gnat. If you want to work on your own machine, you can download sources and binaries for the compiler from the departmental ftp site,, directory pub/gnat. After that, do the following;

a) Create a directory walk, which will hold the tree_walking routine and the test cases.

b) Modify your path so that the GNAT commands are ahead of others: set path=(/usr/local/pkg/gnat/bin $path)

c) The compiler needs the definitions of several environment variables to locate the sources and binaries of the compiler and the library. These definitions are kept in the file env-vals in the home page directory. You can introduce these definitions in your environment by executing:

source /usr/httpd/htdocs_cs/courses/spring01/G22.2130-001/env-vals

or by copying this file into your own directory and executing

source env-vals

which you might just do from you .login file. For reference, here is are its contents:

setenv GCC_EXEC_PREFIX /usr/local/pkg/gnat-3.13p/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.1/ setenv ADA_INCLUDE_PATH /usr/local/pkg/gnat-3.13p/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.1/adainclude:/usr/local/pkg/gnat-3.13p/src/ada setenv ADA_OBJECTS_PATH /usr/local/pkg/gnat-3.13p/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.1/adalib setenv C_INCLUDE_PATH /usr/local/pkg/gnat-3.13p/lib/gcc-lib/sparc-sun-solaris2.5.1/2.8.1/include If you are working on your own installation at home, you need to use the names of the directories on you disk. GCC_EXEC_PREFIX is the directory that contains the compilation commands gnatmake, gcc, etc. ADA_INCLUDE_PATH has two components: the first is the adainclude directory, that includes the sources for the ada run-time components (e.g. IO routines). The second component is the directory that includes the sources of the compiler. This component is needed because the Tree_Walker program uses several components from the compiler itself. The typical Ada user does not need this. ADA_OBJECT_PATH is the adalib directory, that includes the binaries for the run-time libraries. C_INCLUDE_PATH is the include directory that contains the C header files neededffor the run-time. d) Go into the walk directory, and compile the tree-walker routine: gnatmake test_walker A number of .o files and .ali files will appear in that directory. These will be created the first time you build test_walker. You will notice that subsequent compilations will be much faster. e) place the example provided above into file f) Build the tree for this ada program: gcc -c -gnatt g) Run tree-walker on the tree file you just created: test_walker tiny.adt h) Modify the tree-walker routine and have it do something more useful. Apply it to a larger program.

File-Naming rules

A package specification appears in a file with extension .ads (ada specification), a package body appears in a file with extension .adb (ada body). The tree for any compilation unit appears in a file with extension .adt Note that tree files are not text files, you cannot edit them directly.

Command file

#!/bin/csh source ../env-vals gcc -c -gnatv -gnatt gnatmake -gnatv test_walker ./test_walker tiny.adt

Output of tree walker

spunky% ./test_walker tiny.ats Encountered Node Kind : N_COMPILATION_UNIT Encountered Node Kind : N_PACKAGE_DECLARATION Encountered Node Kind : N_PACKAGE_SPECIFICATION Encountered Node Kind : N_OBJECT_DECLARATION Encountered Node Kind : N_SUBPROGRAM_DECLARATION Declaration of foo found on Line 3 Encountered Node Kind : N_SUBPROGRAM_DECLARATION Declaration of bar found on Line 4