I see. So DIANA an intermediate code format, rather than syntax tree format since all sematic analysis must be done on top.
DIANA is a high level intermediate representation where the syntax tree is represented. It is present when the PAR_PHASE is over. With TLALOC you can compile a source text and stop after PAR_PHASE :
./a83.sh ./ ../example.adb S
. Then if you ask for dumping the DIANA tree :
./a83.sh ./ ../example.adb A
In the file $$$_TREE.TXT you have the view of the syntax tree only.
The DIANA network structure is then augmented with nodes from the LIB_PHASE and the SEM_PHASE. You can stop after each of these phases and dump the DIANA tree. After the WRITE_LIB phase the dump is impossible because the DIANA temp file ($$$.TMP) is deleted.
So effectively DIANA contains the syntax tree but is not strictly a syntax tree format.
OK, it looks like a full compiler then.
Yes, let aside the target code optimizer. The LLIR stack machine is handy for the expander and nice for portability but leads to redundant binary code (rax push/pop rbp adjustments, duplicate expressions..). But the price to pay on OoO execution modern processors is perhaps not so terrible. Anyway I cannot deal with too much complexity and the stack machine target is the way to go. The macro production is probably a door open to emitting SSA ops instead of direct processor binary, and then an optimization stage will be possible. But this also introduces a host of problems with a would be debugger for the compiler.
Hi.all ![]()
A short advancement report on Ada 83/TLALOC [EXEC(1)]. With some sweat
, the compiler now compiles multidimensional arrays and records with corresponding aggregates. It passes those in sub-programs parameters. A first compiler compile with the compiler… has been attempted and nearly all TLALOC units have been compiled to fasmg by TLALOC itself (all the front end but 3 units using dynamic allocation not implemented), a good step toward EXEC(2). The code is not presently operational but most of it has good chances to be valid taken into account tests already done. Layout representation clauses of variant record objects contained in a 64 bits machine word will be done next for the DIANA type TREE. The question is : will fasmg take the ~100 code pieces of fasmg macros. If it does, that will be a nice achievement.
It progresses…
Nice work! It’s cool to see this project progressing.
Though I have only superficial knowledge of compilers, my interest would be a DIANA ->Plan 9 asm back end which outputs Plan 9 assembler for each of the supported architectures. Then borrow the existing linkers to build the binaries. I am not sure how complex all of this is but it would be a useful first step to get Ada on Plan 9.
Hi !
The current TLALOC backend directly produces an ELF64 binary through fasmg. No linker is required for now. I have no working knowledge of Plan 9, only superficial infos. But I think that to target Plan 9 on on one of x86-64, aarch64, riscv-64 processors you normally have just to adapt the system services calls which are in codi_x85_64.finc, or codi_arm64.finc, or codi_riscv64.finc . For the moment these are Linux syscalls. I suppose Plan 9 also has syscalls equivalents to output chars, strings, open files… Perhaps some launch addresses in the ELF would change in Plan 9. But I guess the adaptation should not be very difficult. Now, you need fasmg operating on Plan 9 also (and Gnat of course to compile TLALOC EXEC(1).
I have been reading through some of the code trying to get a feel for how the compiler works. The formatting is odd, what editor did you create the source files? It is a bit difficult to read as the line width is huge from all the tabs.
The portable Plan 9 approach would be an expander which outputs Plan 9 assembler for each supported architecture. The Plan 9 kernel architecture is quite different and most operations are done via file IO. Those character, string, time and other syscalls go away and instead you read and write console, time and other files served by the kernel. It also uses its own a.out format, not ELF.
Plan 9 assembler is the machine dependent quasi-LLIR the Plan 9 C compilers output. The loader takes this assembler, loads library code, does the final instruction selection then writes the binary. A compiler, assembler, and loader exist for each supported architecture. e.g. the amd64 compiler 6c will compile hellow.c to hellow.6, a binary P9 assembler file which is passed to 6l, the loader which will output the final hellow binary. This is the tool chain the Go compilers are built on.
Hi !
I mostly use Kate editor on Ubuntu, (sometimes Geany or Jgrasp).
Tabs are 10 characters and source code line length is up to 120 characters. Comments generally start after column 120. An enscript command can be used to separate the 120 columns of source to be printed on one sheet, and another to print comment to print on another page put in front in plastic protection sheets.
Tabs are widely used to have an aerated source code and easy to edit light text files. The long term text block archiving in tools requires minimizing text sizes. These are not common conventions, but after numerous styles trials, I found that the present style proves practical and readable with the adequate editor environment.
Plan 9 “everything is a file” approach.
(just a note, the source code block optimizer program has put some tabs where there should be none, sometimes a unique space has been replaced by a tab which produces an odd result when editing. Something I’ll have to take a look at).
You know there’s a style guide to Ada, right?
Yes…but I prefer mine…
![]()
Is my style so difficult to read (once tabs have been set to 10) ?
![]()
How to do this for browsing in GitHub?
If you have an account,
https://github.com/settings/appearance
Tab size preference
Choose the number of spaces a tab is equal to when rendering code
Hi !
The TLALOC compiler executable generated by Gnat EXEC(1) has produced fasmg macros FINC files for the 73 Ada 83 files of the TLALOC compiler itself (whole EXEC(2)). (./bin/comp_ada_comp.sh script in ./bin).
This is a significant step even if there is high probability that the code itself is not presently directly usable. But it says that the TLALOC frontend/expander couple is able to compile fairly complicated things because the frontend and the expander have been written with Ada 83 “ad libitum”.
Two semantic holes have been discovered in the process : the front end accepts REC.FIELD even if FIELD is not a field of REC (!!). In fact valid Ada 83 is treated correctly, but not all non Ada 83 code is refused by sem_phase.
Also this is accepted by the semantic phase but I think this is not valid Ada 83 :
INACTIVE : BOOLEAN renames TRUE;
Now the target is producing an operating EXEC(2) to compile the source with a complete TLALOC path.
Do you use any test suite, ACATS or something else?
Hi Dmitry !
Until now custom tests have been generated on the fly by AI. The first objective was to compile usable predefined packages. This is nearly complete, but there is no exceptions handling Then compile a bootstrap version of the compiler (that is compile everything that is used in the current version of Ada 83/TLALOC source code). And see if the fasmg approach can be used at the scale of the whole compiler.
The frontend normally passes acvc tests. I’ll have a look at latest acvc11 for Ada 83 and see what is compiled.
This is valid Ada 83: RM 8.5.
A function call is a primary. Also legal and, contrary to the above, overloadable:
function Inactive return Boolean renames True;
BTW: I guess you know Tlaloc is an Aztec god.
What is the source for that generation? Specifically:
- Tests generated from the reference manual text, e.g. the ARM says
A raise_statement with no exception_name (that is, a re-raise statement) shall be within a handler, but not within a body enclosed by that handler.
OK, says the intellect to itself, I am going generate tests with re-raise in a function body, in an entry body, in a package executable part, in a block statement inside a handler, outside a handler and so on.
- Tests generated from the compiler source code.
E.g. in order to get 100% coverage. There is an error message in the source. OK, thinks the intelligence, I am going to write a test to get that message and check the generated test source against the ARM for its legality.
Why is it “on-the-fly”? Logically, once a test is generated it should stay forever in the test suite or equivalent unless indicated as wrong or redundant. Why would you throw it away?
(sorry for being pedantic, but the issue is very interesting to me)
Premiere ! Ada 83/TLALOC compiled and executed acvc test A21001A :
$ ./A21001A
---- A21001A CHECK THAT BASIC CHARACTER SET IS ACCEPTED.
==== A21001A PASSED ============================.
To answer the question of testing until now. When I started writing the EXPANDER I had the goal to compile the predefined packages especially TEXT_IO. Those packages being written in Ada 83, they were a first test of the compiler. To test a bunch of services, I ask Claude or ChatGPT to write a sufficiently exhaustive test program of the services written in Ada 83 and compiled. See for example ./bin/enum_test.adb in the repos, or ./bin/direct_io_test.adb. That is what I call “on the fly” : program the services and test them for what they are expected to do. I do not throw away the main tests, I rather recompile and rerun them after significant modifications.
Now I will try to progress through the acvc 11 tests, in parallel with the compiler compilation. The first A21001A is passed, which is nice because there are some rather delicate Ada 83 string and slices processing. Everything is on the repos framagit and github (in the .bin/ADA__LIB you can see the REPORT.FINC and A21001A.FINC produced. It begins to be impressive in fact.