❌ About FreshRSS

Normal view

There are new articles available, click to refresh the page.
Before yesterdayGautier's blog

LEA, a tiny but smart editor

14 October 2023 at 13:39

Note for subscribers: if you are interested in my Ada programming articles only, you can use this RSS feed link.


LEA, the Lightweight Editor for Ada, is based on the Scintilla text editor widget, which excels at colouring syntactic elements and letting the user rework his or her programs very swiftly, including manipulating rectangular selections and adding text on multiple points (usually vertically aligned).
But until recently, the cool features were limited to automatic indentation, adding comment delimiters (--) at the right column, or highlighting portions of text that match a selection.
Users were frustrated by not finding in LEA programming helpers (commonly grouped under the term "smart editor" or "intellisense") that they enjoy in their programming "studios".
An excuse would have been to dismiss such features as out of the scope of a "lightweight" editor.
But we know we can make of LEA a powerful mini-studio, with the ease of use of a simple editor, thanks to its "projectless" mode and the integrated HAC compiler.
So now, it happened.
From revision 385 of LEA (and revision 886 of HAC), you have now a good sense of intellisense:

  • mouse-hover tips: when you let the mouse pointer on an identifier for a little while, a tip appears about that identifier (typically, where it was declared)
  • context menu with a go-to-declaration entry, when applicable
  • call tips: on typing '(' after a subprogram name, a tip appears with the subprogram's parameters
  • auto-complete: on typing characters that belong to identifiers, a list of possible declared identifier appears; that list depends on where in the source code the text cursor is: declarations below the cursor are invisible and local declarations, possibly within multiple nested subprograms. 

Some screenshots will help illustrate the above points. Let's start with the sudoku_sample.adb example shipped with the HAC project. What's that "Sudo_Strings" type, for instance?
Just let the mouse pointer hang out around an occurrence of that keyword.

Mouse hover tip - Click image to enlarge it

Want to know more about that declaration? Right-click on it...

Go to declaration - Click image to enlarge it

...and here you go.

Declaration in the Sudoku package - Click image to enlarge it

That's it, so far, for features enabling navigation within existing code.
For writing code, here are two other key helpers. First, the call tips.
If we type '(' after a subprogram's name, we see the parameters list appear:


Call tip - Click image to enlarge it

If we type the beginning of an identifier, a list of possible completions appears:

Auto-complete - Click image to enlarge it

A few remarks about the present state of LEA's "smart editor" features:
  • Currently, LEA only supports the HAC subset - it was the first priority. GNAT and other Ada compilers have their own editors and navigation features, so there is a lesser pressure to support them in LEA.
  • The "smart editor" features are quite new and still under test and development. If you want to have them, you need to build LEA on a fresh clone (instructions are given in lea.gpr), then set (via regedit) the registry key SMART_EDITOR, in the branch HKEY_CURRENT_USER\SOFTWARE\LEA\, to "true", before starting LEA.
  • You will notice a few missing things, like a list of fields on typing '.' after a record variable. They are not forgotten and just still "under construction".
  • The "smart editor" features work on incomplete Ada sources. They might be just less present after the point of an error, especially a syntax error.

In order to develop the last point, here are a few examples on how LEA understands your program "on the fly", while you are typing it:

Smart editor on an incomplete piece of code - Click image to enlarge it

Smart editor on an incomplete piece of code, sample 2 - Click image to enlarge it

Smart editor on an incomplete piece of code, sample 3 - Click image to enlarge it

One more thing: the Windows version of LEA is contained in a single executable holding in currently 4.2 MiB, including data such as code samples and templates, and runs as a portable application (no installation required).

Some Web links:

LEA

Web site: http://l-e-a.sf.net/
Sources, site #1: https://sf.net/p/l-e-a/code/HEAD/tree/
Sources, site #2: https://github.com/zertovitch/lea
Alire Crate: Alire - LEA

HAC

Web site: https://hacadacompiler.sourceforge.io/
Sources, site #1: https://sf.net/p/hacadacompiler/code/HEAD/tree/
Sources, site #2: https://github.com/zertovitch/hac
Alire Crate: Alire - HAC

Enjoy!

LEA: first steps as a "smart editor"

2 September 2023 at 19:53

Note for subscribers: if you are interested in my Ada programming articles only, you can use this RSS feed link.


Spot the "tool tip" on the following screenshot...

Click to enlarge

Translation: cross-references and source code navigation in LEA are becoming a reality since this evening!

 


Some Web links:

LEA

Web site: http://l-e-a.sf.net/
Sources, site #1: https://sf.net/p/l-e-a/code/HEAD/tree/
Sources, site #2: https://github.com/zertovitch/lea
Alire Crate: Alire - LEA


Since LEA embeds the HAC compiler, here are a few links about HAC as well:

HAC

Web site: https://hacadacompiler.sourceforge.io/
Sources, site #1: https://sf.net/p/hacadacompiler/code/HEAD/tree/
Sources, site #2: https://github.com/zertovitch/hac
Alire Crate: Alire - HAC

HAC for native targets

20 August 2023 at 13:57
Note for subscribers: if you are interested in my Ada programming articles only, you can use this RSS feed link.

HAC (the HAC Ada Compiler) was since the first of its previous lives, from Pascal-S, in 1973, to recent commits, translating high-level language exclusively to the machine code of a fictitious machine (a Virtual Machine, abbreviated VM).

For writing a tiny compiler, a VM is very convenient:

  • You (the compiler creator) can model and adapt it to your needs.
  • You don't depend on hardware.
  • You don't need to rewrite the code generation for each new hardware.
  • You can make the VM running on many hardwares (hence the success of the JVM and .NET around year 2000).


The HAC VM and its users are enjoying all these advantages.

However, there is a flip side:

  • A VM is much slower than a real machine (but till year 2000, it didn't matter; you could say: don't worry, just wait a few months for a more powerful computer).
  • Since year 2000, the speed of microprocessors stopped doubling every six months (hence the declining interest in Virtual Machines). Despite the improvements in cache, RAM, and the multiplication of cores, the per-core performance improvement is slower and slower.
  • Supporting only a VM gives the impression that your compiler can only compile to a VM.


Well, so far, the latter blame was objectively correct regarding HAC until a few weeks ago.
Now it is changing!
We have begun an abstract framework for emitting machine code.
With that framework, HAC can, on demand, emit code for its captive VM or for any implemented machine.
So you read well, it is not a just-in-time compiler translating VM instructions to native ones.
We are implementing a direct Ada-to-native compiler - and cross-compiler, since HAC doesn't know on which machine it is running!

The framework looks like this:

with HAC_Sys.Defs;

package HAC_Sys.Targets is

  type Machine is limited interface;

  type Abstract_Machine_Reference is access Machine'Class;

  --------------------
  --  Informations  --
  --------------------

  function Name (m : Machine) return String is abstract;
  function CPU (m : Machine) return String is abstract;
  function OS (m : Machine) return String is abstract;
  function Null_Terminated_String_Literals (m : Machine) return Boolean is abstract;

  ----------------------------
  --  Machine Instructions  --
  ----------------------------

  procedure Emit_Arithmetic_Binary_Instruction
    (m         : in out Machine;
     operator  :        Defs.Arithmetic_Binary_Operator;
     base_typ  :        Defs.Numeric_Typ) is abstract;

...


The code emission in the compiler is being changed (very slowly, be patient!) for going through this new abstract machine mechanism.
So far we have two implementations:

  • The HAC VM - that way, we ensure HAC-for-HAC-VM works exactly as previously and can pass the test suite.
  • A real target: the AMD64, running under Windows; the machine code is emitted in Assembler form, for the Flat Assembler (FASM).


The development for multiple targets is embryonic so far.
However, we can already compile a "hello world"-style program:

with HAT;

procedure Native is
  use HAT;
  a : Integer;
begin
  --  a := 1;  --  Variables: TBD.
  Put_Line ("Hello ...");
  Put_Line ("... world!");
  Put_Line (12340 + 5);
  Put_Line (12350 - 5);
  Put_Line (2469 * 5);
  Put_Line (61725 / 5);
end Native;


With the command:
hac -tamd64_windows_console_fasm native.adb

HAC produces this:

;  Assembler file for the Flat Assembler - https://flatassembler.net/

format PE64 console
entry _start
include 'include\win64a.inc'

section '.code' code readable executable

_start:
         push                9
         push                1
         push                -1
         push                -1
         pop                 r14
         pop                 r13
         pop                 r12
         pop                 r11
         add                 r12, _hac_strings_pool
         ccall               [printf], r12
         ccall               [printf], _hac_end_of_line
         push                10
         push                11
         push                -1
         push                -1
         pop                 r14
         pop                 r13
         pop                 r12
         pop                 r11
         add                 r12, _hac_strings_pool
         ccall               [printf], r12
         ccall               [printf], _hac_end_of_line
         push                12340
         push                5
         pop                 r11
         pop                 rax
         add                 rax, r11
         push                rax
         push                20
         push                10
         push                -1
         pop                 r14
         pop                 r13
         pop                 r12
         pop                 r11
         ccall               [printf], _hac_decimal_format, r11
         ccall               [printf], _hac_end_of_line
         push                12350
         push                5
         pop                 r11
         pop                 rax
         sub                 rax, r11
         push                rax
         push                20
         push                10
         push                -1
         pop                 r14
         pop                 r13
         pop                 r12
         pop                 r11
         ccall               [printf], _hac_decimal_format, r11
         ccall               [printf], _hac_end_of_line
         push                2469
         push                5
         pop                 r11
         pop                 rax
         imul                rax, r11
         push                rax
         push                20
         push                10
         push                -1
         pop                 r14
         pop                 r13
         pop                 r12
         pop                 r11
         ccall               [printf], _hac_decimal_format, r11
         ccall               [printf], _hac_end_of_line
         push                61725
         push                5
         pop                 r11
         pop                 rax
         xor                 rdx, rdx
         idiv                r11
         push                rax
         push                20
         push                10
         push                -1
         pop                 r14
         pop                 r13
         pop                 r12
         pop                 r11
         ccall               [printf], _hac_decimal_format, r11
         ccall               [printf], _hac_end_of_line
         stdcall             [ExitProcess],0

section '.data' data readable writeable
_hac_end_of_line  db 10, 0
_hac_decimal_format  db "%d", 0
_hac_strings_pool db "XHello ...", \
    0, "... world!", 0

section '.idata' import data readable
library kernel,'kernel32.dll',\
        msvcrt,'msvcrt.dll'
import  kernel,\
        ExitProcess,'ExitProcess'
import  msvcrt,\
        printf,'printf'

As you can see, the assembler code needs badly some simplification, but, anyway: it works.
FASM produces from it a relatively small 2048-byte executable which writes

Hello ...
... world!
12345
12345
12345
12345


The executable is full of zeroes, due to alignments. The non-zero bytes (more or less, the actual machine code and data) take 605 bytes.

Some Web links for HAC:

Main URL: https://hacadacompiler.sourceforge.io/
Sources, site #1: HAC Ada Compiler download | SourceForge.net
Sources, site #2: GitHub - zertovitch/hac: HAC Ada Compiler - a small, quick Ada compiler fully in Ada
Alire Crate: Alire - Hac

HAC version 0.26

8 July 2023 at 06:40
Note for subscribers: if you are interested in my Ada programming articles only, you can use this RSS feed link.

Main URL: https://hacadacompiler.sourceforge.io/
Sources, site #1: HAC Ada Compiler download | SourceForge.net
Sources, site #2: GitHub - zertovitch/hac: HAC Ada Compiler - a small, quick Ada compiler fully in Ada
Alire Crate: Alire - Hac

What’s new:

  • You can use a loop’s name for the exit statement: exit Loop_Name.
  • You can exit multiple, nested, loops, by using exit Loop_Name.
  • Ada semantics are better verified:
    • Array indexing (i)(j) (array of array) and (i, j) (multi-dimensional array) are no more treated as equivalent (this feature was a remnant of the Pascal syntax).
    • Separation between Type and Subtype declarations (anonymous types are allowed only in the few cases foreseen by the language).
    • Operators of the HAT package (+, -, & for strings) are visible without prefix only in the scope of a use HAT clause.

Note that correct Ada programs, in relation to the above points, were already accepted and parsed correctly by HAC before that change.

Finally, a bit of cosmetics in the build messages:

C:\Ada\hac\exm>..\hac -v2 -c pkg_demo.adb

*******[ HAC ]*******   HAC is free and open-source. Type "hac" for license.
       [ HAC ]          HAC Ada Compiler version 0.26, 08-Jul-2023
       [ HAC ]          Compiling main: pkg_demo.adb
       [ HAC ]          | Compiling x_pkg_demo_s.ads (specification)
       [ HAC ]           \ Compiling x_pkg_demo_s1.ads (specification)
       [ HAC ]            \ Compiling x_pkg_demo_s11.ads (specification)
       [ HAC ]            /           x_pkg_demo_s11.ads: done.
       [ HAC ]            \ Compiling x_pkg_demo_s12.ads (specification)
       [ HAC ]            /           x_pkg_demo_s12.ads: done.
       [ HAC ]            \ Compiling x_pkg_demo_s13.ads (specification)
       [ HAC ]            /           x_pkg_demo_s13.ads: done.
       [ HAC ]           /           x_pkg_demo_s1.ads: done.
       [ HAC ]           \ Compiling x_pkg_demo_s2.ads (specification)
       [ HAC ]            \ Compiling x_pkg_demo_s21.ads (specification)
       [ HAC ]            /           x_pkg_demo_s21.ads: done.
       [ HAC ]            \ Compiling x_pkg_demo_s22.ads (specification)
       [ HAC ]            /           x_pkg_demo_s22.ads: done.
       [ HAC ]            \ Compiling x_pkg_demo_s23.ads (specification)
       [ HAC ]            /           x_pkg_demo_s23.ads: done.
       [ HAC ]           /           x_pkg_demo_s2.ads: done.
       [ HAC ]           \ Compiling x_pkg_demo_s3.ads (specification)
       [ HAC ]            \ Compiling x_pkg_demo_s31.ads (specification)
       [ HAC ]            /           x_pkg_demo_s31.ads: done.
       [ HAC ]            \ Compiling x_pkg_demo_s32.ads (specification)
       [ HAC ]            /           x_pkg_demo_s32.ads: done.
       [ HAC ]            \ Compiling x_pkg_demo_s33.ads (specification)
       [ HAC ]            /           x_pkg_demo_s33.ads: done.
       [ HAC ]           /           x_pkg_demo_s3.ads: done.
       [ HAC ]          |           x_pkg_demo_s.ads: done.
       [ HAC ]          | Compiling x_pkg_demo_m.ads (specification)
       [ HAC ]          |           x_pkg_demo_m.ads: done.
       [ HAC ]          | Compiling x_pkg_demo_b.ads (specification)
       [ HAC ]          |           x_pkg_demo_b.ads: done.
       [ HAC ]          Compilation of pkg_demo.adb (main) completed
       [ HAC ]          ------  Compilation of eventual with'ed unit's bodies
       [ HAC ]          | Compiling x_pkg_demo_s.adb (body)
       [ HAC ]          |           x_pkg_demo_s.adb: done.
       [ HAC ]          | Compiling x_pkg_demo_s1.adb (body)



LEA 0.85 - the Tabs are here!

20 November 2022 at 20:05
Note for subscribers: if you are interested in my Ada programming articles only, you can use this RSS feed link.

The 0.85 version of LEA (the Lightweight Editor for Ada) is available!

Web site: http://l-e-a.sf.net/
Source repository #1: https://sf.net/p/l-e-a/code/HEAD/tree/
Source repository #2: https://github.com/zertovitch/lea

The new version has two main new features:
  - Tabs (screenshot below)
  - LEA doesn't write scilexer.dll as a file; thus, it runs as a portable application (in the sense: you can run it from a read-only drive directly, without installation)

Click to enlarge

Enjoy!

AZip, GWindows, the Windows API and another surprise!

13 November 2022 at 12:38

 

Note for subscribers: if you are interested in my Ada programming articles only, you can use this RSS feed link.


Last post was about an improvement of the GWindows.Common_Controls.Ex_List_View widget which is distributed with the GWindows framework. Without changing the specification, it was possible to avoid Windows API calls during the performance-sensitive comparison function, leading to impressive speedup factors: from 3.3x with 4096 items to 16.5x with 32768 items.

But actually, it was only the prelude!

If you can live with data duplication, which is not nice and not always practical, it is possible to do much better. Concretely, you store the same strings in the cells of the List_View widget and in the payload data associated with each row. Then, the sorting for all columns (text, dates, numbers, ...) is using the payload data. An addition to the Ex_List_View package later (this time, enriching a bit the specification), the comparison function may exclusively use the payload of both compared rows, directly, thus avoiding any API call during the lifespan of the comparison function.

Without going into too many details, here are the performance gains in charts:



This represents a factor of ~100x to ~300x on top of the previous improvement, depending on the test machine.

Here are links to the sources:

AZip:

Project site & Subversion repository:
https://sf.net/projects/azip/
GitHub clone with Git repository:
https://github.com/zertovitch/azip

GWindows:

Project site & Subversion repository:
https://sf.net/projects/gnavi/
GitHub clone with Git repository:
https://github.com/zertovitch/gwindows

LEA 0.84 - the Build & Run button!

12 November 2022 at 11:43

 

Note for subscribers: if you are interested in my Ada programming articles only, you can use this RSS feed link.


The 0.84 version of LEA (the Lightweight Editor for Ada) is available!


Web site: http://l-e-a.sf.net/
Source repository #1: https://sf.net/p/l-e-a/code/HEAD/tree/
Source repository #2: https://github.com/zertovitch/lea

This version is essentialy a rework of LEA's ergonomy - we had recently the chance of having a group of young first-time programmers and first-time LEA users to test it!

The main addition is the green Build & Run button, which matches a (less intuitive) menu entry and the F9 key.

Click screenshot to enlarge

Another addition is a dedicated box for the "User_Abort" internal Virtual Machine exception, so that the LEA user doesn't take the exception message for an actual error (which would be the case for any other exception).

Before:


Now:

Enjoy!


HAC as an embedded compiler

28 June 2022 at 20:32

Here is an example to illustrate how the HAC compiler is embedded in an Ada application.

The user of the application has typically only an executable (built with a "full Ada" system like GNAT) and an "Ada-pplet" (can be a few lines) that is run from that executable.

Normally, applications have different languages for building the application and for the embedded script system: Excel is written in C/C++ but embeds VBA (Visual Basic for Applications). 3D Studio Max has MaxScript. GIMP uses Script-fu, a variant of Scheme. Others use Lua or Python. Of course nobody would think about shipping a software with a scripting language where you have to fight with pointers and conditional compilation (C/C++).

But... how about an application that is written in a compiled language, but is using the same language for its scripting purposes? Since a few days, it is possible with HAC (the HAC Ada Compiler).

If you build the demo exchange_hac_side.adb (e.g. from GNAT Studio, or via the command "gprbuild hac"), you get an executable, exchange_hac_side on Linux or exchange_hac_side.exe on Windows. If you run it, you get:

Exchange_Native_Side is started.

Native: building a HAC program: exchange_hac_side.adb

   Exchange_HAC_Side is started.

   HAC: I call a parameterless callback.
      Native: Parameterless_Callback is speaking!
   HAC: done calling.

   HAC: I send some stuff through callbacks.
      Native: HAC is saying: [I'm HAC and I say hello!]
      Native: HAC has sent me the numbers: 123 456 789
      Native: HAC has sent me the numbers: 1.23000000000000E+02 4.56000000000000E+02 7.89000000000000E+02

   HAC: message before call: [I'm HAC]
      Native: HAC is saying: [I'm HAC]
   HAC: message after call: [No, I'm Native, you loser!]
   HAC: integer before call: [12]
      Native: HAC has sent me the number: 12; I will send it back squared.
   HAC: integer after call: [144]
   HAC: float before call: [11.0]
      Native: HAC has sent me the number: 1.10000000000000E+01; I will send it back squared.
   HAC: float after call: [121.0]

   HAC: integer before call: [13]
        message before call: [I'm a HAC record field]
           enum before call: [BAT]
      Native: Enum = BAT
      Native: Matrix m:
           1.10 1.20
           1.30 1.40
      Native: Matrix n:
          -2.10 2.20
          -2.30 2.40
      Native: Matrix o = m * n:
          -5.07 5.30
          -5.95 6.22
      Native: Enum = CAT
   HAC: integer after call: [169]
        message after call: [I'm a Native message now (niarg niarg niarg)!]
           enum after call: [CAT]
        matrix product:
          -5.07 5.30
          -5.95 6.22

Messages as "Native" are from the main application.

Messages as "HAC" are from the small HAC program that is run from the application.

A little disadvantage of having the same language on both sides... is that it is the same language! It could be confusing at first glance. Plus, it is not in the tradition. That may be disturbing for a number of people.

A big advantage of having the same language is that you can share some pieces of code. For instance the following package is used for building the demo application, and compiled by HAC when the application is running!

------------------------------------------- -- HAC <-> Native data exchange demo -- ------------------------------------------- -- Package used by both HAC and -- -- Native sides -- ------------------------------------------- package Exchange_Common is type Animal is (ant, bat, cat, dog); subtype Beast is Animal; subtype Insect is Animal range ant .. ant; subtype Mammal is Animal range bat .. dog; end Exchange_Common;


HAC (HAC Ada Compiler) is a quick, small, open-source Ada compiler, covering a subset of the Ada language. HAC is itself fully programmed in Ada.

Web site: http://hacadacompiler.sf.net/ 

Source repositories:

 #1 svn: https://sf.net/p/hacadacompiler/code/HEAD/tree/trunk/

 #2 git: https://github.com/zertovitch/hac

Ann: HAC v.0.2

25 June 2022 at 21:35

HAC (HAC Ada Compiler) is a quick, small, open-source Ada
compiler, covering a subset of the Ada language.
HAC is itself fully programmed in Ada.

Web site: http://hacadacompiler.sf.net/
From there, links to sources, and an executable for Windows.

Source repositories:
  #1 svn: https://sf.net/p/hacadacompiler/code/HEAD/tree/trunk/
  #2 git: https://github.com/zertovitch/hac

* Main improvements since v.0.1:

  - a program run by HAC can exchange data with the
      programm running HAC, through dynamically registered call-backs
      - see package HAC_Sys.Interfacing and demos:
        src/apps/exchange_native_side.adb
        src/apps/exchange_hac_side.adb

  - the compiler checks that all choices in a CASE statement
      are covered

  - the compiler performs more compile-time range checks and
      optimizes away useless run-time checks when it's safe to do so.

Enjoy!

Gautier

Ann: HAC v.0.1

14 May 2022 at 12:19

HAC (HAC Ada Compiler) is a quick, small, open-source Ada
compiler, covering a subset of the Ada language.
HAC is itself fully programmed in Ada.

Web site: http://hacadacompiler.sf.net/
From there, links to sources and an executable for Windows.

Source repositories:
  #1 svn: https://sf.net/p/hacadacompiler/code/HEAD/tree/trunk/
  #2 git: https://github.com/zertovitch/hac

* Main improvements since v.0.0996:

  - packages and subpackages are now supported
  - modularity: packages and subprograms can be standalone
      library units, stored in individual files with
      GNAT's naming convention, and accessed from other units
      via the WITH clause
  - validity checks were added for a better detection of
      uninitialized variables.

Package examples and modularity tests have been added.
Particularly, a new PDF producer package with a few demos
is located in the ./exm/pdf directory.


hakoch

Enjoy!

Gautier
__
PS: for Windows, there is an integrated editor that embeds HAC:
LEA: http://l-e-a.sf.net
PPS: HAC will be shown at the Ada-Europe conference (presentation + tutorial)
http://www.ada-europe.org/conference2022/

HAC, packages and PDF

10 May 2022 at 19:51

In order to illustrate a feature, what is better than a visual example?
In our case, the feature is the modularity, recently implemented in HAC (the HAC Ada Compiler).
So, a nice exercise was to try with a "real" visual package, PDF_Out (project Ada PDF Writer, link here).
Of course, HAC is still a small compiler project which doesn't cover all the sexy features of Ada - even those of the first version of Ada, Ada 1983, which already had extensive generics, aggregates (on-the-fly composite objects as expressions), default values in records or in subprogram parameters, exceptions or user-defined operators.
The easy way of down-stripping PDF_Out for HAC was to open the source code in the LEA editor (link here), and do frenetically and iteratively:

loop
  punch the compile key (F4)
  exit when the package compiles!
  make the code HAC-compatible (sometimes, it hurts!)
end loop


A few things that needed a downgrade for the HAC 0.1 language subset were:

  • Object-oriented type extension (tagged type for PDF stream). In the simplified version, PDF files are the only supported PDF streams.
  • Object.method notation
  • Default values in records, replaced by explicit initialization.
  • Inclusion of raster images (NB: the removal of that feature was unnecessary).
  • User-defined exceptions (PDF_stream_not_created, ...).
  • User-defined operators ("+", ...).
  • Indefinite page table and offset table.

The result can be seen here:


Click to enlarge

 

You can experiment it yourself by checking out or cloning the latest version of HAC:

#1 svn: https://sf.net/p/hacadacompiler/code/HEAD/tree/trunk/
#2 git: https://github.com/zertovitch/hac

The new PDF examples are located in the subdirectory ./exm/pdf




HAC: packages - now, the whole package!

11 April 2022 at 22:21

Drum rolls: HAC (the HAC Ada Compiler) now supports packages.

OK, there is still a slight limitation: library-level packages cannot contain variables and constants, nor an initialization part (begin .. end). Removing this limitation would be complex to implement and is postponed so far for HAC.

A new modularity demo can be found in the "exm" subdirectory.
The main file is "pkg_demo.adb".
It is a simple test for simulating the build of an application with numerous dependencies.
The dependencies take form of packages depending on two or more other packages, down to
a certain recursion depth.
Each package contains a procedure with the same name: "Do_it", which just writes a string related to the package name. For instance,  X_Pkg_Demo_B3.Do_it will write "[B3]", then call X_Pkg_Demo_B31.Do_it, X_Pkg_Demo_B32.Do_it, and X_Pkg_Demo_B33.Do_it.
The package dependencies can be seen the following chart:



NB: the depth and number of children can be set as you wish.

How to run the demo?
First, we generate the package tree.
For that, assume you have the "hac[.exe]" executable ready in the main directory.
Note: in what follows, replace '/' by '\' if you are on Windows.
In the "exm" directory, run from the command line: "../hac pkg_demo_gen.adb".
Alternatively, from LEA, load "pkg_demo_gen.adb" and run it (F9).
The packages ("x_*" files) will be generated.

Now, from the command line, run "../hac pkg_demo.adb" (or from LEA, load it and punch F9).

The result is:

     Specs:  [S][S1][S11][S12][S13][S2][S21][S22][S23][S3][S31][S32][S33]    
     Mixed:  [M][M1][M11][M12][M13][M2][M21][M22][M23][M3][M31][M32][M33]    
     Bodies: [B][B1][B11][B12][B13][B2][B21][B22][B23][B3][B31][B32][B33]    

    
If you are curious about how HAC does the whole build the 40 units (main procedure and 39 packages),
add the "-v2" option to the build command: "../hac -v2 pkg_demo.adb".
On an i7 machine (with HAC itself built in "Fast" mode), the time elapsed
for the entire build is around 0.08 seconds. Only one core is used.
Since GNAT builds also the library "on the fly" by automatically
finding dependencies, you can see it in action by doing:
"gnatmake -I../src -j0 pkg_demo"
Interestingly, GNAT compiles the packages for each depth successively.
Then you can see the result by doing:
"./pkg_demo"
Of course, it's identical to HAC's. 

---

HAC (the HAC Ada Compiler) is a small, quick, open-source Ada compiler,
covering a subset of the Ada language.
HAC is itself fully programmed in Ada.

Web site: http://hacadacompiler.sf.net/

Source repositories:
#1 svn: https://sf.net/p/hacadacompiler/code/HEAD/tree/trunk/
#2 git: https://github.com/zertovitch/hac
 

Enjoy!

Gautier


HAC: packages (work in progress)

27 March 2022 at 19:01

Since a few commits, HAC parses packages! But so far there are limitations : it's "work in progress".

Nevertheless you can already play a bit with the things already programmed in HAC.

File prc.ads:

with Pkg_1, Pkg_2;

procedure Prc is
  x : Pkg_1.A;
 
  use Pkg_1, Pkg_2;

  xg : G;
  y : B;
  z : Pkg_1.E;

begin
  x := 0;
  y := 0;
  z := 2;
end;

File pkg_1.ads:

package Pkg_1 is

  subtype A is Integer;
  subtype B is Pkg_1.A;
  subtype C is B range 0 .. 1000;
 
  package Sub_Pkg is    
    subtype D is C range 1 .. 100;    
  end Sub_Pkg;  
 
  subtype E is Sub_Pkg.D range 2 .. 10;
 
end Pkg_1;

File pkg_2.ads:

with Pkg_1;

package Pkg_2 is 

  subtype F is Pkg_1.E;
  use Pkg_1.Sub_Pkg;
  subtype G is D;
 
end Pkg_2;

Now, from the command-line (assume you are in the main hac directory), do:

hac -v2 prc.adb

*******[ HAC ]*******   Compiler version: 0.0997 dated 19-Mar-2022.
*******[ HAC ]*******   Caution: HAC is not a complete Ada compiler. Type "hac" for license.
. . . .[ HAC ]. . . .   Compiling main: prc.adb
. . . .[ HAC ]. . . .   .Compiling: pkg_1.ads (specification)
. . . .[ HAC ]. . . .   .Compilation of pkg_1.ads completed
. . . .[ HAC ]. . . .   .Compiling: pkg_2.ads (specification)
. . . .[ HAC ]. . . .   .Compilation of pkg_2.ads completed
. . . .[ HAC ]. . . .   Compilation of prc.adb (main) completed
. . . .[ HAC ]. . . .   --  Compilation of eventual with'ed unit's bodies  --
. . . .[ HAC ]. . . .   Build finished in 0.001255600 seconds.
. . . .[ HAC ]. . . .   Object code size: 12 of 100000 Virtual Machine instructions.
. . . .[ HAC ]. . . .   Starting p-code VM interpreter...
-------[ HAC ]-------   VM interpreter done after 0.045569300 seconds.
Execution of prc.adb completed.
Maximum stack usage: 10 of 4000000 units, around 0%.

If you want a more complex example of how HAC can create the library "on the fly" by compiling recursively everything needed to build the main procedure, it is already in the examples (subdirectory exm):

*******[ HAC ]*******   Compiler version: 0.0997 dated 19-Mar-2022.
*******[ HAC ]*******   Caution: HAC is not a complete Ada compiler. Type "hac" for license.
. . . .[ HAC ]. . . .   Compiling main: unit_a.adb
. . . .[ HAC ]. . . .   .Compiling: unit_b.ads (specification)
. . . .[ HAC ]. . . .   .Compilation of unit_b.ads completed
. . . .[ HAC ]. . . .   .Compiling: unit_c.adb (body)
. . . .[ HAC ]. . . .   .Compilation of unit_c.adb completed
. . . .[ HAC ]. . . .   Compilation of unit_a.adb (main) completed
. . . .[ HAC ]. . . .   --  Compilation of eventual with'ed unit's bodies  --
. . . .[ HAC ]. . . .   .Compiling: unit_b.adb (body)
. . . .[ HAC ]. . . .   ..Compiling: unit_e.adb (body)
. . . .[ HAC ]. . . .   ..Compilation of unit_e.adb completed
. . . .[ HAC ]. . . .   ..Compiling: unit_f.ads (specification)
. . . .[ HAC ]. . . .   ...Compiling: unit_g.ads (specification)
. . . .[ HAC ]. . . .   ...Compilation of unit_g.ads completed
. . . .[ HAC ]. . . .   ..Compilation of unit_f.ads completed
. . . .[ HAC ]. . . .   .Compilation of unit_b.adb completed
. . . .[ HAC ]. . . .   --  Compiled bodies: 1
. . . .[ HAC ]. . . .   .Compiling: unit_f.adb (body)
. . . .[ HAC ]. . . .   .Compilation of unit_f.adb completed
. . . .[ HAC ]. . . .   .Compiling: unit_g.adb (body)
. . . .[ HAC ]. . . .   .Compilation of unit_g.adb completed
. . . .[ HAC ]. . . .   --  Compiled bodies: 2
. . . .[ HAC ]. . . .   Build finished in 0.006483700 seconds.
. . . .[ HAC ]. . . .   Object code size: 350 of 100000 Virtual Machine instructions.
. . . .[ HAC ]. . . .   Starting p-code VM interpreter...
Unit_A: demo of modularity features for subprograms.

------

HAC (HAC Ada Compiler) is a small, quick, open-source Ada compiler,
covering a subset of the Ada language.
HAC is itself fully programmed in Ada.

Web site: http://hacadacompiler.sf.net/

Source repositories:
#1 svn: https://sf.net/p/hacadacompiler/code/HEAD/tree/trunk/
#2 git: https://github.com/zertovitch/hac
 

Enjoy!


Gautier

Ann: HAC v.0.0996

22 January 2022 at 09:53

HAC (HAC Ada Compiler) is a small, quick, open-source Ada compiler,
covering a subset of the Ada language.
HAC is itself fully programmed in Ada.

Web site: http://hacadacompiler.sf.net/

Source repositories:
#1 svn: https://sf.net/p/hacadacompiler/code/HEAD/tree/trunk/
#2 git: https://github.com/zertovitch/hac

Main improvements since v.0.095:

  • range checks on discrete subtype assignment (:=) and conversion
  • short-circuit logical operators: "and then", "or else"
  • for S = Scalar subtype: S'First, S'Last, S'Succ, S'Pred, S'Pos, S'Val, S'Image, S'Value, S'Range attributes
  • for A = array object or array subtype: A'First [(N)], A'Last [(N)], A'Range [(N)], A'Length [(N)] attributes
  • "&", "<", ">", "=", "/=" operators defined for the String type (additionally to HAL.VString type)
  • CASE choices admit ranges
  • forward declarations for subprograms


Enjoy!

Gautier

PS: for Windows there is an integrated editor that embeds HAC:
LEA: http://l-e-a.sf.net

A curiosity with LZMA data compression

10 August 2021 at 09:42

Uncompressed file: 1'029'744 bytes.

Compressed size (excluding Zip or 7z archive metadata; data is not preprocessed):

BytesCompressed / Uncompressed ratio Format Software
172'976 16.80% PPMd 7-Zip 21.02 alpha
130'280 12.65% BZip2 Zip 3.0
119'327 11.59% BZip2 7-Zip 21.02 alpha
61'584 5.98% LZMA Zip-Ada v.57
50'398 4.89% LZMA2 7-Zip 21.02 alpha
50'396 4.89% LZMA 7-Zip 21.02 alpha
42'439 4.12% LZMA Zip-Ada v.58 (preview)
41'661 4.05% LZMA Zip-Ada (current research branch)

Conclusion: the Zip-Ada (current research branch) compresses that data 17.3% better than 7-Zip v.21.02!

The file (zipped to its smallest compressed size, 4.05%) can be downloaded here. It is part of the old Canterbury corpus benchmark file collection (file name: kennedy.xls).

Please don't draw any conclusion: the test data is a relatively small, special binary file with lots of redundancy.
But that result is a hint that some more juice can be extracted from the LZMA format.

The open-source Zip-Ada project can be found here and here.

HAC v.0.095

7 April 2021 at 20:13

A bit of brush-up after our last post about the new modularity features of HAC (the HAC Ada Compiler), we can announce the release of version 0.095.

We have tested since then parameters to units, and the use of functions instead of procedures as units.

All that with the LEA editor, in order to experiment the behaviour of compile-time errors and run-time errors. In contrast to the command-line tool called "hac" where everything is forgotten once the command is run, whatever the outcome, in an integrated editor the compiler needs to close files properly in every case - also on errors, because the editor will open them to show the error locations. Similarily, the builder needs to clear the library information between two builds. The improvements to be made to HAC for a smooth functioning were straightforward. Just a couple of statements to add here and there.

A demo of HAC's current modularity support, in one picture:

Click to enlarge

HAC (HAC Ada Compiler) is a small, quick, open-source Ada compiler,
covering a subset of the Ada language.
HAC is itself fully programmed in Ada.

HAC web site: http://hacadacompiler.sf.net/


Source repositories:
 #1 svn: https://sf.net/p/hacadacompiler/code/HEAD/tree/trunk/
 #2 git: https://github.com/zertovitch/hac

Enjoy!

HAC built with ObjectAda 10.2

6 December 2020 at 14:31

When you think that your software is highly compiler- and operating-system-independent, it is only a guess until you can verify it.

For HAC (the HAC Ada Compiler), the OS-independence is easy to verify thanks to GNAT, the well-known free Ada compiler.

Regarding the full independence, it is a bit trickier. There are two items (which are subprograms in the HAC_Pack package), that are intrinsically non-portable and not covered by the standard Ada libraries whose authors bear the burden of finding implementations:

  package Non_Standard is
    procedure Sys (Command : String; Result : out Integer);
    function Directory_Separator return Character;
  end Non_Standard;

Two subprograms in 12595 lines of code spanning over 59 source files (revision #306) - it's not a such a big deal.

So a real test was to build HAC with the ObjectAda64 for Windows development environment.

Surprise (but with Ada, it was still a bit expected...): the build went completely seamlessly once I had selected "Ada 2012" in the project settings (HAC's source use a few Ada 2012 features).

Zero error, and the real surprise: zero warning.

The ObjectAda implementation for the above package Non_Standard actually required more work than building the Ada sources (basically, a few mouse clicks). For Directory_Separator, it was easy since we could hardcode '\' given the Windows target. For the procedure Sys, we were able to use the same C function (system) as for the C library that comes with GNAT since the Microsoft run-time imitates some Unix (and then GNU) functionalities. Then, having the linker finding system was the real challenge. Basically if you reference the Win32 library in the project, the linker somehow finds system. Don't ask me how, it's part of the mysteries of the tools that emulate modularity for C (to say things politely).

Enough dirty details, here is a screenshot:

ObjectAda's Integrated Development Environment, right after a complete build of HAC. Click to enlarge.

HAC is free and open-source, sources can be found here and here.


Some research with LZMA...

28 November 2020 at 19:54

A rare case where Zip-Ada's LZMA encoder is much better than LZMA SDK's. Rare but still interesting, and with standard LZMA parameters (no specific tuning for that file):


The compressed size with current revision (rev.#882) of Zip-Ada is slightly worse (42,559 bytes).

The file is part of the classic Canterbury Corpus compression benchmark data set.

Zip-Ada: the new Zip_Entry_Stream output stream

2 September 2020 at 13:05

The latest addition to Zip-Ada (commits #792 to 794) is the possibility of writing contents to a Zip file (or more generally, a Zip stream) as an output stream. You (the programmer) don't need to store contents into some buffer and design an input stream in the Zip_Streams.Root_Zipstream_Type'Class type class to read that buffer, as it is the case for Add_Stream in the Zip_Create package.

How does new output stream work in practice? The best way is to show an example. Here is a reduced version of Test_Zip_Entry_Stream (you can find the full version in the test directory of the Zip-Ada project's sources):

      with Zip.Create;
with Ada.Command_Line, Ada.Text_IO;

procedure Test_Zip_Entry_Stream is
use Zip.Create;
use Ada.Command_Line, Ada.Text_IO;

Archive_Info : Zip_Create_Info;
Archive_File : aliased Zip_File_Stream;
Archive_Entry : aliased Zip_Entry_Stream_Type;
Text : File_Type;
begin
Create_Archive (Archive_Info, Archive_File'Unchecked_Access, "test_zes.zip");
for I in 1 .. Argument_Count loop
Open (Archive_Entry);
Open (Text, In_File, Argument (I));
while not End_Of_File (Text) loop
String'Write (Archive_Entry'Access, Get_Line (Text));
Character'Write (Archive_Entry'Access, ASCII.LF); -- UNIX end-of-line
end loop;
Close (Text);
Close (Archive_Entry, "zes_" & Argument (I), use_clock, Archive_Info);
end loop;
Finish (Archive_Info);
end Test_Zip_Entry_Stream;

Enjoy!

NB: this addition has been sponsored. It is used in an industrial software (robotics).

The open-source Zip-Ada project can be found at the following places:

❌
❌