1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-21 02:27:10 +03:00
mal/ada.2
2019-03-17 14:15:41 +01:00
..
core.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
core.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
Dockerfile ada.2: add Dockerfile from kanaka 2019-03-17 14:15:41 +01:00
envs.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
envs.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
err.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
err.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
eval_cb.ads ada2: rename to ada.2 2019-03-10 01:25:07 +01:00
Makefile ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
printer.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
printer.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
reader.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
reader.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
readline.adb ada2: rename to ada.2 2019-03-10 01:25:07 +01:00
readline.ads ada2: rename to ada.2 2019-03-10 01:25:07 +01:00
README ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
run ada2: rename to ada.2 2019-03-10 01:25:07 +01:00
step0_repl.adb ada2: rename to ada.2 2019-03-10 01:25:07 +01:00
step1_read_print.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
step2_eval.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
step3_env.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
step4_if_fn_do.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
step5_tco.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
step6_file.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
step7_quote.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
step8_macros.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
step9_try.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
stepa_mal.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-atoms.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-atoms.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-builtins.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-builtins.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-fns.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-fns.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-mal.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-mal.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-maps.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-maps.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-sequences.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-sequences.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-symbols-names.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-symbols.adb ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types-symbols.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00
types.ads ada.2: spring cleaning before final pull request. 2019-03-17 14:03:38 +01:00

Comparison with the first Ada implementation.
--

The first implementation was deliberately compatible with all Ada
compilers, while this one illustrates various Ada 2020 features:
assertions, preconditions, invariants, initial assignment for limited
types, limited imports, indexing aspects...

The variant MAL type is implemented with a discriminant instead of
object-style dispatching.  This allows more static and dynamic checks,
but also two crucial performance improvements:
* Nil, boolean, integers and pointers to built-in functions are passed
  by value without dynamic allocation.
* Lists are implemented as C-style arrays, and most of them can be
  allocated on the stack.

Once each component has an explicit interface, various optimizations
have been added: unique allocation of symbols, stack-style allocation
of environments in the current execution path, reuse of allocated
memory when the reference count reaches 1...

The eventual performances compete with C-style languages, allthough
all user input is checked (implicit language-defined checks like array
bounds and discriminant consistency are only enabled during tests).

There are also similarities with the first implementation.  For
example, both rely on user-defined finalization to count references in
recursive structures instead of a posteriori garbage collection.

Notes for contributors that do not fit in a specific package.
--

* All packages can call Eval back via a reference in the Eval_Cb
  package, set during startup. I am interested in a prettier solution
  ensuring a valid value during elaboration.
  Note that generic packages cannot export access values.

* All wrapped pointers are non null, new variables must be assigned
  immediately. This is usually enforced by a hidden discriminant, but
  here we want the type to become a field inside Types.Mal.T. So the
  check happens at run time with a private invariant.

* The finalize procedure may be called twice, so it does nothing when
  the reference count is zero, meaning that we are reaching Finalize
  recursively.

* In implementations, a consistent object (that will be deallocated
  automatically) must be built before any exception is raised by user
  code (for example the 'map' built-in function may run user code).

* Each module encapsulating dynamic allocation counts allocations and
  deallocations. With debugging options, a failure is reported if
  - too many deallocation happen (via a numeric range check)
  - all storage is not freed (via a dedicated call from the step file)

Known bugs
--

The third step of the perf^ada2 target fails during the final storage
deallocation when the executable is built with -gnatp. I have failed
to understand why so far.

Debugging
--

Uncaught exceptions are reported with an execution trace (excluding
TCO cycles).  This has become possible in step9, but has been
backported to former steps as this is really handy for debugging.

Some environment variables increase verbosity.
# dbg_reader= ./stepAmal     trace reader recursion
# dbgeval=    ./stepAmal     eval recursion (or TCO)
# dbgenv0=    ./stepAmal     eval recursion and environments contents
# dbgenv1=    ./stepAmal     eval recursion and environment internals