[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 1/2] Fix typo for PKG_CONFIG_PATH
|
From: |
Guillermo E. Martinez |
|
Subject: |
[PATCH 1/2] Fix typo for PKG_CONFIG_PATH |
|
Date: |
Mon, 22 Feb 2021 17:46:00 -0600 |
2021-02-18 Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
* HACKING: Fix typo.
---
HACKING | 2120 -------------------------------------------------------
1 file changed, 2120 deletions(-)
delete mode 100644 HACKING
diff --git a/HACKING b/HACKING
deleted file mode 100644
index a296fe2f..00000000
--- a/HACKING
+++ /dev/null
@@ -1,2120 +0,0 @@
- __________________________
-
- GNU POKE - HACKING NOTES
-
- The poke hackers
- __________________________
-
-
-Table of Contents
-_________________
-
-1. Nomenclature
-2. Maintenance
-.. 1. Global Maintainer
-.. 2. Global Reviewers
-.. 3. Maintainers
-.. 4. Write After Approval
-.. 5. Personal Branches
-.. 6. Building Release Tarballs
-.. 7. Installing Obvious Changes
-.. 8. The poke.rec database
-.. 9. The source for this HACKING file
-.. 10. The Bugzilla
-..... 1. Dealing with spam in the Bugzilla
-.. 11. Recording noteworthy development changes
-3. Development Environment
-.. 1. Autotools
-.. 2. Dejagnu
-.. 3. Flex
-.. 4. Bison
-.. 5. Jitter
-.. 6. Building
-.. 7. Building after a git pull
-.. 8. Gettext
-.. 9. Running an Uninstalled Poke
-.. 10. Continuous Integration
-4. Coding Style and Conventions
-.. 1. Writing C
-..... 1. Avoid Tabs
-..... 2. Avoid bool
-..... 3. Use _p for Predicates
-..... 4. Documenting Functions in Public Headers
-.. 2. Writing Poke
-.. 3. Writing RAS
-..... 1. RAS Emacs mode
-..... 2. Calling compiled Poke from RAS
-5. Writing Tests
-.. 1. Test framework
-.. 2. Unit Tests
-.. 3. Naming Tests
-.. 4. Always set obase
-.. 5. Put each test in its own file
-.. 6. List the test files in testsuite/Makefile.am
-.. 7. dg-output may require a newline
-.. 8. Using data files in tests
-.. 9. Using NBD connections in tests
-.. 10. Writing tests that depend on a certain capability
-.. 11. Writing REPL tests
-.. 12. Testing Pickles
-..... 1. Command REPL tests
-..... 2. General REPL tests
-6. Writing Documentation
-.. 1. Documenting Pickles
-7. Fuzzing poke
-.. 1. Grammarinator
-8. Submitting a Patch
-9. Maintenance
-10. Poke Architecture
-11. The Poke Compiler
-.. 1. Compiler Overview
-.. 2. The bison Parser in pkl-tab.y
-.. 3. The AST
-..... 1. Loop Statements
-.. 4. Compiler Passes and Phases
-..... 1. Naming Conventions for Phases
-..... 2. Naming Conventions for Handlers
-..... 3. Transformation Phases
-..... 4. Analysis Phases
-..... 5. Type System Phases
-..... 6. Front and Middle End Handlers should be Re-entrant
-.. 5. Adding Compiler Built-Ins
-12. The Poke Virtual Machine
-.. 1. Exception Handling
-.. 2. Signal Handling
-.. 3. Offsets and bit-offsets in the PVM
-13. Memory Management
-.. 1. Using ASTREF
-.. 2. Using ASTDEREF
-.. 3. PVM values in PVM programs
-.. 4. PVM values in AST nodes
-14. Terminal Handling
-.. 1. pk-term
-.. 2. Styling Classes
-.. 3. Debugging Styling
-15. Debugging poke
-.. 1. Building with Debugging support
-.. 2. Invoking GDB to debug an uninstalled poke
-.. 3. Using GDB extensions
-.. 4. Valgrind and Poke
-.. 5. Debugging PVM Assembly Code
-16. Profiling poke
-.. 1. Building with profiling support
-
-
-Welcome, adventurous poker! This file contains useful information for
-you.
-
-Copyright (C) 2019-2021 The poke authors.
-
-This file is part of GNU poke.
-
-GNU poke is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation, either version 3 of the License, or (at your
-option) any later version.
-
-GNU poke is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License along
-with GNU poke. If not, see <https://www.gnu.org/licenses/>.
-
-
-1 Nomenclature
-==============
-
- We call `poke' the program. When the context may induce confusion
- (since `poke' is a pretty common word) then we use `GNU poke'.
-
- `Poke' (with upper case P) is the name of the domain-specific language
- implemented by `poke', the program.
-
- A `pickle' is a Poke source file containing definitions of types,
- variables, functions, etc, that conceptually apply to some definite
- domain. For example, `elf.pk' is a pickle that provides facilities to
- poke ELF object files. Pickles are not necessarily related to file
- formats: a set of functions to work with bit patterns, for example,
- could be implemented in a pickle `bitpatterns.pk'.
-
-
-2 Maintenance
-=============
-
-2.1 Global Maintainer
-~~~~~~~~~~~~~~~~~~~~~
-
- Jose E. Marchesi <jemarch@gnu.org>
-
-
-2.2 Global Reviewers
-~~~~~~~~~~~~~~~~~~~~
-
- Jose E. Marchesi <jemarch@gnu.org>
-
-
-2.3 Maintainers
-~~~~~~~~~~~~~~~
-
- Maintainers are individuals who are responsible for, and have
- permission to check in changes in, certain subsets of the code, and
- push them to the master branch. Note that that maintainers still need
- approval to check in changes outside of the immediate domain that they
- maintain.
-
- Note also that maintainers are still asked to send [COMMITTED]
- messages to the list with the patches they push. This helps to keep
- the other hackers aware of what is going on in other areas.
-
- etc/poke-mode.el Aurélien Aptel <aaptel@suse.com>
-
-
-2.4 Write After Approval
-~~~~~~~~~~~~~~~~~~~~~~~~
-
- The people below have write access to the git repository, and can
- install their changes after getting explicit approval from a global
- reviewer.
-
- Egeyar Bagcioglu <egeyar@gmail.com>
- John Darrington <jmd@gnu.org>
- Luca Saiu <positron@gnu.org>
- Darshit Shah <darnir@gnu.org>
- Dan Čermák <dan.cermak@cgc-instruments.com>
- Bruno Haible <bruno@clisp.org>
- Carlo Caione <ccaione@baylibre.com>
- Eric Blake <eblake@redhat.com>
- Tim Ruehsen <tim.ruehsen@gmx.de>
- Kostas Chasialis <sdi1600195@di.uoa.gr>
- Aurélien Aptel <aaptel@suse.com>
- Mohammad-Reza Nabipoor <m.nabipoor@yahoo.com>
- David Faust <david.faust@oracle.com>
-
-
-2.5 Personal Branches
-~~~~~~~~~~~~~~~~~~~~~
-
- Anyone having write access to the git repository is allowed to push
- and maintain personal branches. These branches should be called
- `WHO/WHAT', where `WHO' is the nick identifying the owner of the
- branch and `WHAT' a description of what it contains.
-
- Example:
-
- ,----
- | jemarch/hyperlinks-server
- `----
-
-
- Personal branches are intended to ease the interaction between
- developers, and to provide a convenient basis for testing large
- changes.
-
- Personal branches can be rebased, and deleted. Please do not write
- into a personal branch unless you have the explicit approval of the
- branch owner.
-
-
-2.6 Building Release Tarballs
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The standard target `make distcheck' builds a distributable sources
- tarball, and tests that it can be built and tested properly.
-
-
-2.7 Installing Obvious Changes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Anyone having write access to the git repository is allowed to push
- obvious changes to non-personal branches. The "obvious" category
- includes typos in comments, renaming of variables, etc.
-
- If you commit and push an obvious change, you are still required to
- send an email to the mailing list stating you installed the change.
- Please include a suggestive tag in your email's subject, something
- like `[COMMITTED]'. Also, make sure to include the patch itself.
-
-
-2.8 The poke.rec database
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
- We maintain a database in `etc/poke.rec', in the form of a recfile.
- See <http://www.gnu.org/software/recutils> for more information on
- recfiles.
-
- This database is kept up to date by the maintainer, and contains lots
- of information on the current tasks to do, bugs, release, asn so on.
- See the comment at the top of `poke.rec' for more information.
-
-
-2.9 The source for this HACKING file
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- This file (HACKING) is an ASCII export of the org-mode file in
- etc/hacking.org. In order to regenerate it, you have two options:
-
- - You can open it in Emacs and run the `org-export-dispatch' function.
- Replace the current contents of HACKING with the output.
-
- - You can run `make update-hacking' at the top build directory. This
- will execute Emacs in batch mode and update HACKING.
-
-
-2.10 The Bugzilla
-~~~~~~~~~~~~~~~~~
-
- We maintain a bugs database in <https://www.sourceware.org/bugzilla>.
- Our product is `poke', which is divided in several components
- corresponding to the several areas of the program/project.
-
- If you find a bug and you don't want or you can't work on it, please
- file a bug there providing as much details as you can.
-
- If the bugzilla URL ever changes it should be updated in
- `configure.ac'.
-
- Once a new bug is submitted to bugzilla, a maintainer will eventually
- look at it and, if confirmed as a bug, will add an entry for it to
- `etc/poke.rec'.
-
-
-2.10.1 Dealing with spam in the Bugzilla
-----------------------------------------
-
- Sometimes the bugzilla at sourceware gets some spam, in the form of
- bugs containing crap. If you see one, you can flag is as spam by
- transitioning the following fields::
-
- Component -> spam
- Product -> web
- Assigneee -> nobody@sourceware.org
- Status -> Closed as invalid
-
-
-2.11 Recording noteworthy development changes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Sometimes the development of poke can be fast, and may be difficult
- for hackers to stay up to date with the latest modifications and
- changes. The DEV-NEWS file records noteworthy changes in a terse way,
- and it is intended to be a helper for developers.
-
- If you change or add something that you think should be noted by other
- hackers, such as the addition of a new API, or a change in an existing
- interface, or a new auxiliary tool, or ... please consider adding a
- record to DEV-NEWS
-
-
-3 Development Environment
-=========================
-
- The packages listed in the file DEPENDENCIES are needed.
- Additionally:
-
-
-3.1 Autotools
-~~~~~~~~~~~~~
-
- This distribution uses whatever versions of Automake, Autoconf, and
- Gettext are listed in NEWS; usually the latest ones released. If you
- are getting the sources from git (or change configure.ac), you'll need
- to have these tools installed to (re)build. You'll also need
- help2man. All of these programs are available from
- <ftp://ftp.gnu.org/gnu>.
-
-
-3.2 Dejagnu
-~~~~~~~~~~~
-
- The poke testsuite uses DejaGNU. Please install it if you intend to
- run the tests. If you want to hack poke, you definitely want to run
- the tests :)
-
-
-3.3 Flex
-~~~~~~~~
-
- You will need a recent version of flex, since we are using some recent
- options like "reentrant" or "bison-bridge". flex version 2.6.1 works
- fine.
-
-
-3.4 Bison
-~~~~~~~~~
-
- In order to improve the user's experience, we are using fairly recent
- versions of bison. Bison 3.6.0 or later is required to boostrap and
- build poke from git.
-
-
-3.5 Jitter
-~~~~~~~~~~
-
- In order to build and run poke, you need Luca Saiu's jitter. Jitter
- is available at <http://ageinghacker.net/git/cgit.cgi/jitter>.
-
- The appropriate version of Jitter is now downloaded and bootstrapped
- automatically by Poke's `bootstrap' script, which frees the user from
- the annoyance of installing Jitter as a dependency.
-
- Configuring and compiling Poke will also compile and configure Jitter
- in a subdirectory. Jitter, when configured in `sub-package mode' as
- Poke does, only generates static libraries and requires no
- installation.
-
-
-3.6 Building
-~~~~~~~~~~~~
-
- After getting the git sources, and installing the tools above, you can
- run:
-
- ,----
- | $ ./bootstrap --skip-po
- `----
-
-
- Then, you can run `configure', as described in the files INSTALL and
- INSTALL.generic. For example:
-
- ,----
- | $ mkdir build/ && cd build
- | $ ../configure
- `----
-
-
- Finally:
-
- ,----
- | $ make
- | $ make check
- `----
-
-
-3.7 Building after a git pull
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Usually issuing a `make' at the top build directory is enough to
- rebuild poke after changes have been fetched from the source repo.
- The Automake maintainer-mode rules will make sure that autoconf and
- friends are run again and do the right thing.
-
- However, when the Jitter submodule is updated, you have to first
- bootstrap:
-
- $ ./bootstrap
-
- Then go to the top build directory, and issue a configure explicitly
- before rebuilding:
-
- $ cd build && ../configure $ make
-
- You can't rely on the maintainer-mode rules there, because of certain
- problem with the sub-package mode of Jitter.
-
-
-3.8 Gettext
-~~~~~~~~~~~
-
- When updating gettext, besides the normal installation on the system,
- it is necessary to run gettextize -f in this hierarchy to update the
- po/ infrastructure. After doing so, rerun gnulib-tool --import since
- otherwise older files will have been imported. See the Gnulib manual
- for more information.
-
-
-3.9 Running an Uninstalled Poke
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Once poke is compiled, you can run it before installing by using the
- `run' script built into the root of your build tree; this takes care
- of setting variables such as `PATH', `POKEDATADIR', `POKESTYLESDIR',
- and `POKEPICKLESDIR' to point at appropriate locations.
-
- For example:
-
- ,----
- | $ pwd
- | /home/jemarch/gnu/hacks/poke/build/
- | $ ./run poke
- `----
-
-
-3.10 Continuous Integration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The package is built automatically, at regular intervals. You find
- the latest build results here:
-
- ,----
- | https://gitlab.com/gnu-poke/ci-distcheck/pipelines
- | https://gitlab.com/gnu-poke/ci-distcheck/-/jobs?scope=finished
- `----
-
-
-4 Coding Style and Conventions
-==============================
-
-4.1 Writing C
-~~~~~~~~~~~~~
-
- In Poke we follow the GNU Coding Standards. Please see
- <https://www.gnu.org/prep/standards/>.
-
- Additionally, we have a few conventions that we ask you to follow when
- hacking poke, in order to keep a coherent style when possible. These
- are documented in the following subsections.
-
-
-4.1.1 Avoid Tabs
-----------------
-
- Please format your code using spaces. Tabs (Ascii 9) should not
- appear anywhere except in Makefiles.
-
-
-4.1.2 Avoid bool
-----------------
-
- C99 defines the type `bool'. However, in poke we prefer to use
- variables of type `int' in order to hold truth values. We kindly ask
- you to do the same.
-
- When documenting functions that receive or return boolean values
- stored in integer variables, please remember that the interpretation
- of the truth values in C is: zero means false, and any value other
- than zero means true. Avoid referring to 1 to mean true.
-
- Also, please never rely on a boolean to hold exactly 1 or any other
- particular non-zero value, to be interpreted as true.
-
-
-4.1.3 Use _p for Predicates
----------------------------
-
- We use the venerable convention of using a suffix `_p' (for predicate)
- when naming variables and struct fiels that contain booleans.
-
- We do not always do this, but it is especially important in cases
- where the name of the variable is not indicative enough.
-
-
-4.1.4 Documenting Functions in Public Headers
----------------------------------------------
-
- Function prototypes in headers must be documented using a comment
- block preceding the prototype.
-
- Start the comment block with a terse short sentence that states what
- the function does. Then, document the arguments that the function
- takes, and the value it returns, if any. When referring to arguments
- and other variables in the comment block, please use caps.
-
- It is ok for single comment block to document more than one prototype.
-
- Please leave an empty line between the comment block and the function
- prototype.
-
- Example:
-
- ,----
- | /* Frobnicate a frob.
- |
- | FROB is a frob that should have been previously initialized using
- | frob_new.
- |
- | LAZY_P is a boolean. If true, FROB won't be frobnicated
- | immediately, but instead marked for later frobnication.
- |
- | If the frob cannot be frobnicated, this function returns NULL.
- | Otherwise the function returns the given frob. */
- |
- | frob_t frobnicate (frob_t frob, int lazy_p);
- | frob_t forbnicate_r (frob_t frob, int lazy_p);
- `----
-
-
-4.2 Writing Poke
-~~~~~~~~~~~~~~~~
-
- We recommend to use the Emacs mode in `etc/poke-mode.el' to write
- `.pk' files.
-
- - Do not separate magnitudes and units when writing offsets. Do it
- like this:
-
- ,----
- | 16#B
- `----
-
-
- instead of:
-
- ,----
- | 16 #B
- `----
-
- - Use Camel_Case for type names, but do not use Camel_Case for
- variable/function names!
-
- - Surround pretty-printed values with `#<' and `>.' This is to notify
- the reader that the value has been pretty-printed.
-
-
-4.3 Writing RAS
-~~~~~~~~~~~~~~~
-
-4.3.1 RAS Emacs mode
---------------------
-
- We recommend to use the Emacs mode in `etc/poke-ras-mode.el' to write
- `.pks' files.
-
-
-4.3.2 Calling compiled Poke from RAS
-------------------------------------
-
- A big part of the code generated by the PKL code generator is written
- by hand, in `.pks' files. Sometimes it is convenient to call compiled
- Poke code from that code; for example, to execute complex formulae or
- to perform some operation defined recursively.
-
- In these situations, the solution is to first write a Poke function in
- the compiler's runtime library, `pkl-rt.pk', like:
-
- ,----
- | fun _pkl_foo = (uint<64> ival, uint<64> eval,
- | uint<32> ivalw, uint<32> fieldw) uint<64>:
- | {
- | return ival | (eval <<. (ivalw - fieldw));
- | }
- `----
-
-
- Then, the function can be invoked from the hand-written RAS file using
- the `.call' directive:
-
- ,----
- | .call _pkl_foo
- `----
-
-
- Note how the compiler internal functions use the `_pkl_' prefix. Also
- note that `.call' can only invoke functions defined in the global
- environment.
-
-
-5 Writing Tests
-===============
-
- The poke testsuites live in the `testsuite/' subdirectory. This
- section contains useful hints for adding tests there.
-
-
-5.1 Test framework
-~~~~~~~~~~~~~~~~~~
-
- The test suite is based on DejaGnu, for which you find the general
- documentation at
- <https://www.gnu.org/software/dejagnu/manual/index.html>
-
- The documentation of specific DejaGnu directives is at
- <https://gcc.gnu.org/onlinedocs/gccint/Directives.html>
- <https://gcc.gnu.org/wiki/HowToPrepareATestcase>
-
-
-5.2 Unit Tests
-~~~~~~~~~~~~~~
-
- We are using DejaGnu's support for unit tests. See
- `testsuite/poke.libpoke' for an example on how to write C unit tests.
-
-
-5.3 Naming Tests
-~~~~~~~~~~~~~~~~
-
- For testing a functionality `foo', name your test `foo.pk' or
- `foo-N.pk' where `N' is a number.
-
- If the test is a `do-compile' whose compilation is expected to fail,
- name the test `func-diag.pk' or `func-diag-N.pk'. Here "diag" means
- diagnostic.
-
-
-5.4 Always set obase
-~~~~~~~~~~~~~~~~~~~~
-
- If your test relies on printing integer values in the REPL (or using
- the `%v' formatting tag in a `printf') please make sure to set an
- explicit output numerical base, like in:
-
- ,----
- | /* { dg-command {.set obase 10} } */
- `----
-
-
- This way, we won't have to change the tests if at some point we change
- the default obase.
-
-
-5.5 Put each test in its own file
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- If you are writing tests for a specific functionality, like for
- example a standard function `foo', it may seem logical to put all the
- tests in a single file `foo.pk' like:
-
- ,----
- | /* { dg-do run } */
- |
- | /* { dg-command {foo (1)} } */
- | /* { dg-output "expected result" } */
- |
- | /* { dg-command {foo (1)} } */
- | /* { dg-output "\nexpected result" } */
- |
- | [... and so on ...]
- `----
-
-
- However, this is not a good idea. If some of the "subtests" fail, it
- becomes difficult to determine which one is the culprit looking at the
- test log file.
-
- It is better to put each test in its own file: `foo-1.pk', `foo-2.pk'
- and so on.
-
-
-5.6 List the test files in testsuite/Makefile.am
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- So that the tests get distributed, you need to list each newly added
- test file in testsuite/Makefile.am.
-
- We have a syntax-check target that checks that EXTRA_DIST contains all
- the test files under `testsuite/', and that there is no test listed in
- EXTRA_DIST that doesn't exist in the file system.
-
-
-5.7 dg-output may require a newline
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- If despite the advise above you really need to put more than dg-output
- in a dg-run test file, please be aware you need to prefix all of them
- (but the first one) with a newline, like in:
-
- ,----
- | /* { dg-output "foo" } */
- | /* { dg-output "\nbar" } */
- | /* { dg-output "\n baz" } */
- `----
-
-
-5.8 Using data files in tests
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- If your test requires mapping data, the dg-data directive is what you
- need. It has two forms.
-
- The first form looks like:
-
- ,----
- | /* { dg-data {c*} {0x10 0x20 0x30 0x40 ...} } */
- `----
-
-
- This creates a temporary file (whose name is irrelevant) and makes it
- the current IO space at poke initialization time. The test body, and
- dg-commands, can then map on it.
-
- However, sometimes you need to map on several files. In this case,
- you can have several dg-data entries with an additional argument,
- which is the name of the temporary file to create:
-
- ,----
- | /* { dg-data {c*} {0x01 0x02 ...} foo.data } */
- | /* { dg-data {c*} {0x11 0x12 ...} bar.data } */
- |
- | [...]
- |
- | /* { dg-command { var foo = open ("foo.data") } } */
- `----
-
-
- The file created by the last dg-data (be it anonymous or named) is the
- current IO space.
-
-
-5.9 Using NBD connections in tests
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- If your test requires an NBD server (only useful when poke is compiled
- with libnbd), the dg-nbd directive is what you need. It has one form:
-
- ,----
- | /* { dg-nbd { 0x1 0x2 ...} [dg-tmpdir]/sock } */
- `----
-
-
- This utilizes nbdkit to serve an in-memory disk with initial contents
- over a named Unix socket. Note that the data argument is not the same
- as for dg-data (which uses tcl's binary command), but rather the
- syntax accepted by nbdkit-data-plugin's data= argument, although the
- two are similar. nbdkit then creates a Unix socket server for the
- data, and will be shut down gracefully when the testsuite completes.
- Use of the utility directive [dg-tmpdir] ensures that the socket name
- will not be too long while still respecting $TMPDIR (defaulting to a
- new subdirectory of /tmp), since $objdir may be arbitrarily deep.
-
- To use the server as an IO space, your test will then follow up with:
-
- ,----
- | /* { dg-command "open (\"nbd+unix:///?socket=[dg-tmpdir]/sock\")" } */
- `----
-
-
-5.10 Writing tests that depend on a certain capability
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Sometimes the presence of the functionality tested may be optional.
- An example is testing the support for styling, which depends on poke
- to be built with libtextstyle support.
-
- The dg-require directive can be used for this purpose. For example,
- the following test will be skipped (with status UNSUPPORTED) if the
- capability `libtextstyle' is not found in poke:
-
- ,----
- | /* { dg-do run } */
- | /* { dg-options "--color=html" } */
- | /* { dg-require libtextstyle } */
- |
- | /* { dg-command {printf "%<foo:%i32d%>", 10} } */
- | /* { dg-output "<span class=\"foo\">10</span>" } */
- `----
-
-
- IMPORTANT NOTE: dg-require should appear before any dg-command
- directive in the test file.
-
- The supported capabilities are:
-
- libtextstyle
- poke is built with libtextstyle support.
- nbd
- poke is built with NBD io space support, and dg-nbd works.
-
-
-5.11 Writing REPL tests
-~~~~~~~~~~~~~~~~~~~~~~~
-
- Th the `poke.repl' testsuite is intended to test features in the
- interactive usage of poke. Therefore, it is not dg-based. Instead,
- it uses the services provided by `testsuite/lib/poke.exp'. In a
- nutshell, these services are:
-
- poke_start
- Run a new poke process and wait at the prompt.
- poke_exit
- Exit poke.
- poke_test_cmd CMD PATTERN
- Send CMD to poke, and expect the result PATTERN. CMD is sent as
- virtual keystrokes. Therefore, sending \t or \n has the same
- effect on the REPL than typing TAB or RET in the keyboard,
- respectively. PATTERN shouldn't include the prompt.
- poke_send INPUT PATTERN
- Send INPUT to poke, and expect PATTERN as output.
- poke_send_signal SIGNAL
- Send SIGNAL to poke.
-
- Adding a new test to `poke.repl' involves editing `poke.repl/repl.exp'
- and adding some content there. The following subsections detail how.
-
-
-5.12 Testing Pickles
-~~~~~~~~~~~~~~~~~~~~
-
- Each pickle in `pickles/FOO.pk' shall have a test file
- `testsuite/poke.pickles/FOO-test.pk' written using pickle `pktest'.
-
- If there are some features in the pickle that cannot be tested using
- `pktest' (e.g., pickle uses `print'), that pickle also shall have a
- testsuite in `testsuite/poke.FOO' with a driver
- `testsuite/poke.FOO/FOO.exp'.
-
-
-5.12.1 Command REPL tests
--------------------------
-
- Some REPL tests need to check whether poke replies properly to some
- sent command. The `poke_test_cmd' procedure defined in
- `testsuite/lib/poke.exp' provides a convenient interface for this.
-
- For example:
-
- ,----
- | set test "slashes are preserved"
- | poke_start
- | poke_test_cmd {4 / 2} {2}
- | poke_exit
- `----
-
-
- The snippet above implements a test named "slashes are preserved" that
- runs poke and sends the command `4 / 2' with expected result `2'.
-
- The dialogue when the test above is executed is:
-
- ,----
- | (poke) 4 / 2
- | 2
- | (poke)
- `----
-
-
-5.12.2 General REPL tests
--------------------------
-
- Other REPL tests are not about executing commands. Suppose for
- example we want to test whether tab-completion works. We would write
- something like:
-
- ,----
- | set test "tab-completion-2"
- | poke_start
- | poke_send ".e\t\t" "\r\n.editor .exit *\r\n$poke_prompt .e"
- | poke_exit
- `----
-
-
- The test above uses the `poke_send' procedure, defined in
- `testsuite/lib/poke.exp'. This procedure gets two arguments: the
- input that is sent to poke, and the expected output. Note how usign
- `poke_send' doesn't require poke to execute any command.
-
- Using `poke_send' is more laborious than using `poke_test_cmd': it is
- necessary to explicitly include the prompt in the expected output
- whenever needed.
-
- Note also how newlines are perceived by expect as the sequence `\r\n'.
-
-
-6 Writing Documentation
-=======================
-
-6.1 Documenting Pickles
-~~~~~~~~~~~~~~~~~~~~~~~
-
- The chapter `Pickles' in the Poke manual contains several sections
- organized in thematic areas. When adding a new pickle, find the area
- appropriate for the abstractions provided by the pickle (or create one
- if it doesn't exist already) and add a section for it.
-
- Please make sure to document any dependency of your pickle to other
- pickles.
-
- Keep a tutorial-like tone: for fine details, the user can always go
- and look to the pickle directly.
-
-
-7 Fuzzing poke
-==============
-
-7.1 Grammarinator
-~~~~~~~~~~~~~~~~~
-
- *grammarinator* is a random test generator/fuzzer that creates test
- cases according to an input antlr4 grammar.
-
- In order to generate Poke programs with grammarinator, follow the
- following steps.
-
- First of all, install grammarinator:
-
- ,----
- | $ git clone https://github.com/renatahodovan/grammarinator
- | $ cd grammarinator
- | $ sudo python3 setup.py install
- `----
-
-
- Then, use `grammarinator-process' in order to create the "unparser"
- and "unlexer" for poke:
-
- ,----
- | $ grammarinator-process ../path/to/poke.g4
- `----
-
-
- This will create two files in the current working directory:
- `pokeUnlexer.py' and `pokeUnparser.py'. Next step is to use
- `grammarinator-generate' in order to create tests:
-
- ,----
- | $ grammarinator-generate -l pokeUnlexer.py -p pokeUnparser.py \
- | -r program -n 100 -d 10 \
- | -t grammarinator.runtime.simple_space_transformer
- `----
-
-
- The option `-n' specifies the number of tests (Poke programs) to
- generate.
-
- The option `-d' specifies the maximum recursive level. The bigger the
- recursive level, the bigger the test files will be. If you don't
- specify a maximum recursive level then grammarinator-generate will
- crash.
-
- The option `-t grammarinator.runtime.simple_space_transformer' makes
- sure that whitespaces get inserted between literal tokens.
-
-
-8 Submitting a Patch
-====================
-
- If you hack a feature/improvement/bugfix for poke and want to get it
- integrated upstream, please keep the following points in mind:
-
- - If your patch changes the user-visible characteristics of poke,
- please include an update for the user manual.
-
- - If your patch adds or changes the way poke works internally, in a
- significant way, please consider including an update for the
- `HACKING' file.
-
- - Please include a GNU-style ChangeLog in the patch description, but
- do not include it in the thunks. This is to ease reviewers to apply
- your patch for testing. Of course, include the thunk in the final
- push! (We will get rid of manual ChangeLog entries soon.)
-
- - Make sure to run `make syntax-check' before submitting the patch,
- and fix any reported problem. Note that the maintainer reviewing
- your patch will also do this, so this is a great time to save an
- iteration ;)
-
- - Let's keep poke.git master linear... no merges please. Pull with
- `--ff-only'.
-
- - Send the patch to the `poke-devel' mailing list.
-
- - Use text email only. No html please.
-
- - Inline the patch in the body of your email, or alternatively attach
- it as `text/x-diff' or `text/x-patch'. This is to ease reviewers to
- quote parts of the patch.
-
-
-9 Maintenance
-=============
-
- This section describes `make' targets that performs several
- maintenance tasks.
-
- syntax-check
- Run several syntax-related checks in the source files. It is
- useful to run this target before submitting code to be reviewed,
- and while reviewing other people's code.
-
- Note that sometimes the results have to be taken with a pinch of
- salt. This happens, for example, when a rule oriented to C is
- applied to, say, an AWK file. In these cases, consider adding a
- `.x-sc_*' fine-tuning file. But please ask in poke-devel first.
-
- We provide a pre-push git hook that performs the syntax check
- right before pushing. If the check fails, the push is
- aborted. You should consider enabling this check by coping
- `etc/git-hooks/pre-push' to `.git/hooks/'.
- coverage
- This target builds *poke* with code coverage support, runs the
- testsuite, and generates a nice html report under
- `$(top_builddir)/doc/coverage/'. It is necessary to have the
- `lcov' program for this to work.
- cyclo-poke.html
- This target runs the pmccabe utility to calculate the modified
- cyclomatic complexity of the functions composing the poke
- sources, and generates a nice html report.
- refresh-po
- This target download the latest available translations from the
- translation project and installs them in the source tree.
- update-copyright
- Run this rule once per year (usually early in January) to update
- all the copyright years in the project. By default this
- excludes all variants of COPYING. Exceptions to this procedure
- (such as `ChangeLog..*' for rotated change logs) can be added in
- the file `.x-update-copyright'.
-
-
-10 Poke Architecture
-====================
-
- This figure depicts the overall architecture of poke:
-
- ,----
- | +----------+
- | | compiler |
- | +----------+ +------+
- | | | |
- | v | |
- | +----------+ | |
- | | PVM | <--->| IO |
- | +----------+ | |
- | ^ | |
- | | | |
- | v +------+
- | +----------+
- | | command |
- | +----------+
- `----
-
- The compiler, PVM and IO subsystems are provided by a shared library
- `libpoke'.
-
- The command subsystem resides in the `poke' executable.
-
-
-11 The Poke Compiler
-====================
-
-11.1 Compiler Overview
-~~~~~~~~~~~~~~~~~~~~~~
-
- This figure depicts the architecture of the compiler:
-
- ,----
- | /--------\
- | | source |
- | \---+----/
- | |
- | v
- | +-----------------+
- | | Parser |
- | +-----------------+
- | | analysis and |
- | | transformation |
- | | phases |
- | +-----------------+
- | | code generation |
- | | phase |
- | +-----------------+
- | | Macro assembler |
- | +-----------------+
- | |
- | v
- | /---------\
- | | program |
- | \---------/
- `----
-
-
-11.2 The bison Parser in pkl-tab.y
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The only purpose of the bison parser in pkl-tab.y is to do the
- syntactic analysis, build the initial AST, and set the locations of
- the AST nodes.
-
- Unfortunately, currently it also does some extra work, due to
- limitations in the LARL parser:
-
- - It builds the compile-time environment and register type, variable
- and function declarations.
- - It annotates variables with their lexical addresses.
- - It links return statements with their containing functions.
- - It annotates return statements with he number of lexical frames they
- should pop before exiting the function.
-
- As we shall see below, any further analysis and transformations on the
- AST are performed by the compiler phases, which are implemented
- elsewhere. This greatly helps to keep the parser code clean and easy
- to read, and also eases changing the syntactic structure of poke
- programs.
-
-
-11.3 The AST
-~~~~~~~~~~~~
-
- The compiler operates on an abstract syntax tree that represent the
- program being compiled. The following subsections discuss some
- aspects of the structure of the AST.
-
-
-11.3.1 Loop Statements
-----------------------
-
- Loop statements are represented with trees like:
-
- ,----
- | loop_stmt
- | |
- | +-- [iterator]
- | | |
- | | +-- decl
- | | +-- container
- | |
- | +-- [condition]
- | +-- body
- `----
-
-
- Different kind of loop statements supported in Poke are represented
- including or not including optional fields.
-
- `while' statements with a condition:
-
- ,----
- | while (CONDITION) BODY
- `----
-
-
- are represented as:
-
- ,----
- | loop_stmt
- | |
- | +-- condition
- | +-- body
- `----
-
-
- `while' statements without a condition:
-
- ,----
- | while () BODY
- `----
-
-
- are represented as:
-
- ,----
- | loop_stmt
- | |
- | +-- body
- `----
-
-
- `for-in' statements:
-
- ,----
- | for (VAR in CONTAINER) BODY
- `----
-
-
- are represented as:
-
- ,----
- | loop_stmt
- | |
- | +-- iterator
- | | |
- | | +-- decl (VAR
- | | +-- container
- | |
- | +-- body
- `----
-
-
- `for-in-where' statements:
-
- ,----
- | for (VAR in CONTAINER where SELECTOR) BODY
- `----
-
-
- are represented as:
-
- ,----
- | loop_stmt
- | |
- | +-- iterator
- | | |
- | | +-- decl (VAR)
- | | +-- container
- | |
- | +-- condition (SELECTOR)
- | +-- body
- `----
-
-
-11.4 Compiler Passes and Phases
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- These are the phases currently implemented in the poke compiler:
-
- ,----
- | [parser]
- | --- Front-end pass
- | trans1 Transformation phase 1.
- | anal1 Analysis phase 1.
- | typify1 Type analysis and transformation 1.
- | promo Operand promotion phase.
- | trans2 Transformation phase 2.
- | fold Constant folding.
- | trans3 Transformation phase 3.
- | typify2 Type analysis and transformation 2.
- | anal2 Analysis phase 2.
- | --- Middle-end pass
- | fold Constant folding.
- | trans4 Transformation phase 4.
- | analf Analysis final phase.
- | --- Back-end pass
- | gen Code generation.
- `----
-
- The phases above are organized in several passes:
-
- Pass1
- trans1 anal1 typify1 promo trans2 fold trans3 typify2 anal2
- Pass2
- fold trans4 analf
- Pass3
- gen
-
-
-11.4.1 Naming Conventions for Phases
-------------------------------------
-
- We use the following convention to name phases:
-
- ,----
- | {NAME}{SUFFIX}
- `----
-
-
- where `NAME' reflects a phase category (see below) and `SUFFIX' is
- usually an integer that specifies the order in which the phases are
- applied. Thus, for example, `name4' is performed after `name1'.
- Sometimes, `SUFFIX' is `f' (meaning "final").
-
- The suffix is not used if there is only one phase in the given
- category.
-
- We use the following phase categories:
-
- anal
- For phases whose main purpose is to perform checks on the AST,
- and/or the contents of the AST nodes, and emit errors/warnings.
- trans
- For phases whose main purpose is to alter the structure of the
- AST, and/or the contents of the AST nodes.
- typify
- For phases whose main purpose is to perform type checks, and
- otherwise do work on types.
- promo
- For phases whose main purpose is to perform coercions wherever
- appropriate. Currently there is only one phase in this
- category.
- fold
- For phases whose main purpose is to pre-compute areas of the AST
- whenever it is possible to do so at compile-time. Currently
- there is only one phase in this category, that performs constant
- folding.
- gen
- For phases whose main purpose is to generate PVM code.
- Currently there is only one phase in this category.
-
- The phases in category `NAME' are implemented in the source files
- `libpoke/pkl-NAME.[ch]'.
-
-
-11.4.2 Naming Conventions for Handlers
---------------------------------------
-
- We use the following convention to name phase handlers:
-
- ,----
- | pkl_PHASE_{ps,pr}_NODE
- `----
-
-
- where `PHASE' can be a complete phase name (like `typify1') if the
- handler is to be installed in that phase only, or a phase category
- name (like `typify') if the handler is to be installed in several
- phases in that category. If the phase is to be executed in pre-order,
- `pr' follows, otherwise, `ps'. Finally, `NODE' is the name of the AST
- node.
-
- For example, the handler:
-
- ,----
- | pkl_anal1_ps_comp_stmt
- `----
-
-
- is installed in the phase `anal1', executes in post-order, and serves
- the AST nodes with code `PKL_AST_COMP_STMT'.
-
-
-11.4.3 Transformation Phases
-----------------------------
-
- trans1
- - Finishes strings by expanding sequences, emitting diagnostics
- if an invalid sequence is found.
- - Computes and set the number of elements in STRUCT nodes.
- - Computes and sets the number of elements, fields and
- declarations in struct TYPE nodes.
- - Completes offsets with implicit magnitude by adding a
- magnitude of int<32>1.
- - Calculates the number of arguments in FUNCALL nodes.
- - Annotates declaration nodes as being directly contained in
- struct type nodes.
- - Annotates variables that refer to recursive function calls as
- recursive.
- - Annotates variables with the enclosing function, and with
- their lexical nesting level with respect the beginning of the
- enclosing function.
- - Variables that refer to parameterless functions are
- transformed into funcalls to these functions.
- - Finalizes ATTR node by determining the operation corresponding
- to the attribute name, turning the IDENTIFIERxEXP binary
- expression into an unary expression.
- - Annotates a function's first optional argument and the number
- of formal arguments.
- - Completes function types with their number of formal
- arguments, annotates its first optional argument, and
- determines whether the function type gets a vararg.
- - Completes trimmers with implicit indexes, i.e. [N:], [:N] or
- [:], by adding the missing index as an appropriate expression.
- - Decodes format strings in printf statements.
- - Computes and sets the indexes of all the elements of an ARRAY
- node (array literal) and sets the size of the array.
- - Annotates compound statements with the number of variable and
- function declarations occurring within the statement.
- trans2
- - Annotates expression nodes that are literals, i.e. expressions
- whose values can be computed at compile-time.
- - Annotates offsets, arrays, indexers, trimmers, structs, struct
- references, and casts as literals.
- - Turn struct references that refer to parameterless methods
- into funcalls to these methods.
- - In offsets whose units are type names, make sure these types
- are complete and replace the unit with an expression that
- evaluates to the size of the unit type, in bits.
- trans3
- - SIZEOF nodes whose operand is a complete type are replaced
- with an offset.
-
-
-11.4.4 Analysis Phases
-----------------------
-
- anal1
- - Checks that the elements in struct literals have unique names.
- - Checks that the elements in struct types have unique names.
- - Checks that declarations in unions appear before any of the
- alternatives.
- - Checks that builtin compound statements don't contain
- statements.
- - Check that the actual arguments passed to a funcall are all
- either named or none named.
- - Check that named arguments to funcalls are passed only once.
- - Check that all optional formal arguments in a function
- specifier are located at the end of the arguments list.
- - Check that function specifiers have at most one vararg
- argument, and that it is located at the end of the formal
- arguments list.
- - Check that function types have at most one vararg argument,
- and that it is located at the end of the formal arguments
- list.
- - Check that every BREAK statement have a containing statement.
- - Check that every RETURN statement have a containing function.
- - If the unit in an offset type specifier is specified using an
- integral constant, this constant should be bigger than zero.
- - The unit of an offset literal, if expressed as an integral,
- shall be bigger than zero.
- - Check that the bit count operator in left shift operations are
- less than the number of bits of the shifted operand. This is
- checked in cases where the bit count is constant.
- - Methods can only be defined in a struct type.
- - The initializing expressions in unit declarations should be
- integer nodes.
- - Only methods can call other methods.
- - Methods are not allowed to refer to variables and functions
- defined in struct types.
- - A method can only refer to struct fields and methods defined
- in the same struct type.
- - Functions recursively defined inside methods are not allowed
- to refer to struct fields and methods.
- - Only methods can assign struct fields as variables.
- anal2
- - Every expression, array and struct node should be annotated
- with a type, and the type's completeness should have been
- determined.
- - The magnitude in offset literals should be an integral
- expression.
- - The magnitude in offset literals should have a type and its
- completeness should be known.
- - A return statement returning a value is not allowed in a void
- function.
- - An expressionless return statement is invalid in a non-void
- function.
- - A funcall to a void function is only allowed in an
- expression-statement.
- - Endianness specifiers in struct fields are only valid when
- applied to integral types.
- - In unions, alternatives appearing after an alternative with no
- constraint expression, or a constant expression known to be
- true, are unreachable. Warn about this.
- - If an union alternative has a constraint known to be false, it
- is never taken. Warn about this.
- - Optional fields are not supported in unions.
- - The indexes in array initializers should be constant.
- analf
- - Every array initializer should have an index.
- - Check that the left-hand side of assignment statements are of
- the right kind.
-
-
-11.4.5 Type System Phases
--------------------------
-
- typify1
- - Checks that the expression in which a funcall is applied is a
- function, and that the types of the formal parameters mach the
- types of the funcall arguments.
- - Checks that void functions are not called in contexts where a
- value is expected.
- typify2
- - Checks that the type of the expression in a return statement
- matches the return type of its containing function.
-
-
-11.4.6 Front and Middle End Handlers should be Re-entrant
----------------------------------------------------------
-
- When a type is referenced by name, for example in a map:
-
- ,----
- | Foo @ 0#B
- `----
-
-
- The AST associated with the type is processed again thru the compiler
- middle-end phases. This means that if a handler modifies an AST
- subtree, it should either do it in a way the new structure will be
- still valid if submitted to the same handler again.
-
- An example of this is the `pkl_trans1_ps_print_stmt' handler.
-
- More generally, the front-end and middle-end passes are restartable.
- This means that every handler in these phases shall be re-entrant: if
- executed more than once, they should do The Right Thing (TM).
-
-
-11.5 Adding Compiler Built-Ins
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Compiler built-ins are predefined functions, provided by the compiler,
- that generate particular assembler instructions.
-
- The first step in defining a new built-in is to make the lexer to
- recognize tokens of the form `__PKL_BUILTIN_NAME__' where `NAME' is
- some meaningful name, like for example `RAND':
-
- ,----
- | "__PKL_BUILTIN_RAND__" { return BUILTIN_RAND; }
- `----
-
-
- Then, add a new rule to the rule `comp_stmt' in the bison parser.
- Built-ins are equivalent to compound statements. For example, this is
- the rule for the rand built-in:
-
- ,----
- | | pushlevel BUILTIN_RAND
- | {
- | $$ = pkl_ast_make_builtin (pkl_parser->ast,
- | PKL_AST_BUILTIN_RAND);
- | PKL_AST_LOC ($$) = @$;
- |
- | /* Pop the frame pushed by the `pushlevel' above. */
- | pkl_parser->env = pkl_env_pop_frame (pkl_parser->env);
- | }
- `----
-
-
- Next step is to generate the code for the built-in. This is done
- expanding the `pkl_gen_ps_comp_stmt' rule in the code generation.
- Keep in mind that the generated code should conform a valid function
- body. For example, this is the code generation part for rand:
-
- ,----
- | case PKL_AST_BUILTIN_RAND:
- | pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_RAND);
- | pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_RETURN);
- | break;
- `----
-
-
- ,----
- | The final step is to define the built-in function proper, in the
- | compiler run-time, in =pkl-rt.pk=:
- `----
-
-
- ,----
- | fun rand = int<32>: __PKL_BUILTIN_RAND__;
- `----
-
-
-12 The Poke Virtual Machine
-===========================
-
-12.1 Exception Handling
-~~~~~~~~~~~~~~~~~~~~~~~
-
- Exception types or codes are signed 32-bit integers, and are defined
- in `libpoke/pkl-rt.pk' as `EC_*' variables.
-
- The exceptions themselves are struct values of type Exception, also
- defined in `libpoke/pkl-rt.pk'.
-
- There are two ways an exception can be raised in the PVM:
-
- - Explicitly, when the instruction `raise' is executed.
- - Implicitly, when some instruction needs to fail. For example, an
- integer division instruction divides by zero.
-
- In either case, the treatment of a raised exception is the same:
-
- 1. Pop an exception handler from the exception handler stack.
- 2. If the exception handler matches the raised exception type, then
- i. Restore the heights of the main and return stacks. ii. Restore
- the dynamic environment. iii. Push the cached exception type to
- the stack. iv. Branch to the exception handler.
- 3. Repeat.
-
- The default exception handler, which catches "unhandled" exceptions,
- is installed by the macro-assembler in `libpoke/pkl-asm.c:pkl_asm_new'
- and `libpoke/pkl-asm.c:pkl_asm_finish'. It calls the function
- `_pkl_exception_handler', that is defined in the compiler runtime in
- `libpoke/pkl-rt.pkl'.
-
-
-12.2 Signal Handling
-~~~~~~~~~~~~~~~~~~~~
-
- When the PVM is about to execute a program, it installs a signal
- handler that, at the moment, handles `SIGINT'. This signal handler is
- defined in the `late-c' block in pvm.jitter, and records the signal in
- the PVM internal state.
-
- Then, when a `sync' instruction is executed, it checks the PVM
- internal state and raises a `PVM_E_SIGNAL' exception if there is some
- pending signal. The default signal handler just ignores this signal,
- but the user can also intercept it if desired. The PKL compiler
- generates `sync' instructions in strategic places, such as before
- backward jumps in loops.
-
- The `exit' PVM instruction clears the pending signals in the internal
- PVM state.
-
-
-12.3 Offsets and bit-offsets in the PVM
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The PVM supports a `pvm_off' boxed value, to denote pairs of
- magnitudes and units. Both accessor macros (in `pvm-val.h') and PVM
- instructions (`ogetm', `ogetu') are provided to access their
- components.
-
- Many other PVM entities need to denote offsets in a way or another.
- For example, struct fields in `pvm_struct' values need to record their
- relative offset with respect the beginning of the struct.
-
- It may come to mind, quite naturally, to use `pvm_off' values to
- denote these offsets. It is very elegant. However, we decided to use
- "bit offsets" instead, stored in 64-bit `pvm_long' values.
-
- There are two reasons for this:
-
- - First of all, performance. It is fairly common to operate with the
- absolute value of these offsets, in bits. In fact, in most cases
- that is the only purpose of maintaining them. Having them stored in
- `pvm_off' values means we have to multiply every time we want to get
- their magnitude. This is a waste, for no good reason.
- - To avoid code coupling. PVM offsets are very cool, but they are
- also complex: the unit is arbitrary. This means in many cases we
- have to assume the nature of the unit, mainly bits. This is very
- fragile.
-
- So, the take-home message is: in the PVM, restrict the presence of
- `pvm_off' values to the ones generated by the code generator.
- Whenever an offset is needed in some internal PVM structure, use
- bit-offsets instead encoded as `ulong<64>' values.
-
-
-13 Memory Management
-====================
-
- Different parts of poke use different strategies for memory
- management:
-
- - The compiler front-end uses reference counting to handle AST nodes.
-
- - The PVM uses the Boehm GC collector for values and the run-time
- environment.
-
- - Everything else uses `malloc=/=free'.
-
- This sometimes leads to tricky situations, some of which are
- documented in the subsections below.
-
-
-13.1 Using ASTREF
-~~~~~~~~~~~~~~~~~
-
- The AST uses reference counting in order to manage the memory used by
- the nodes. Every time you store a pointer to an AST node, you should
- use the `ASTREF' function in order to increase its counter:
-
- ,----
- | pkl_ast_node foo = ASTREF (node);
- `----
-
-
- Note that the `pkl_ast_make_*' constructors do `ASTREF' internally, so
- you don't need to use it in calls like:
-
- ,----
- | pkl_ast_node new = pkl_ast_make_struct (ast, 5, elems_node);
- `----
-
-
- To make sure you get the reference counting right, it's required to
- use the return value of `ASTREF' function. The compiler will warn you
- otherwise.
-
-
-13.2 Using ASTDEREF
-~~~~~~~~~~~~~~~~~~~
-
- `ASTDEREF' decreases the reference counter of the provided AST
- node. It's required to use the return value of `ASTDEREF'. The
- compiler will warn you otherwise.
-
- In practice you will seldom find yourself in the need to use
- `ASTDEREF'. Just make sure that every `ASTREF' is paired with a
- `pkl_ast_node_free'.
-
- However, there are situations where `ASTDEREF' is necessary in order
- to avoid a memory leak. For example, consider transformations like `a
- -> b' to `a -> x -> b'. In that case, you should use something like:
-
- ,----
- | b = PKL_AST_KIND_WHAT (node);
- | x = pkl_ast_make_xxx (ast, ASTDEREF (b));
- | PKL_AST_KIND_WHAT (node) = ASTREF (x);
- `----
-
-
- This works because `pkl_ast_make_xxx' does an `ASTREF' to `b'
- internally. The final result is that the reference counter of `b'
- doesn't change at all.
-
-
-13.3 PVM values in PVM programs
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- PVM routines (data structures of type `pvm_routine') are allocated by
- Jitter in complicated data structures, internally relying on `malloc'.
- Their content is therefore not automatically visible to the GC.
-
- Now, the instructions in a routine can contain literal PVM values, and
- some of these values will be boxed. For example, the following
- routine contains a pointer to a `pvm_val_box':
-
- ,----
- | ;; Initialize the element index to 0UL, and put it
- | ;; in a local.
- | push ulong<64>0
- | regvar $eidx
- `----
-
-
- There is only one place where jitter routines are stored in other data
- structures: the PVM program abstraction.
-
- PVM programs are allocated using `pvm_alloc', i.e. by the GC. They
- are composed by a PVM routine and other fields:
-
- ,----
- | struct pvm_program
- | {
- | pvm_routine routine;
- | [...]
- | }
- `----
-
-
- However, since `routine' is malloc-allocated, the GC can't traverse
- it. Consequently, the references to contained boxed values won't be
- accounted for, and these values will be collected if there are no more
- references to them!
-
- The solution, recommended by Luca Saiu, is to keep an array of
- pointers in the PVM program structure, containing the pointers to
- every boxed value used in `routine':
-
- ,----
- | struct pvm_program
- | {
- | pvm_routine routine;
- | void **pointers;
- | [...]
- | };
- `----
-
-
- The pointers are collected in the `pvm-program.c' functions that
- append parameters to instructions.
-
-
-13.4 PVM values in AST nodes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Storing a PVM value (whose memory is handled by GC) in an AST node
- (reference-counted) leads to a problem: the GC is unable to see the
- reference to values, and will therefore collect the memory if there
- are no other reachable references.
-
- Let's see an example of this. Both array and struct types contain
- closures for mappers, writers, bounders, and the like. For example,
- let's take arrays:
-
- ,----
- | struct pkl_ast_type
- | {
- | ...
- | struct
- | {
- | union pkl_ast_node *bound;
- | union pkl_ast_node *etype;
- | pvm_val mapper;
- | pvm_val writer;
- | pvm_val bounder;
- | } array;
- | }
- `----
-
- In this case, `mapper', `writer' and `bounder' are managed by GC.
- However, the contained `struct pkl_ast_type' is not. There is no way
- the GC can find these nodes thru the AST node.
-
- The solution is to declare the relevant pointers in the containing AST
- node as GC roots. The right place to do that is in the corresponding
- constructor in `pkl-ast.c'. For example:
-
- ,----
- | pkl_ast_node
- | pkl_ast_make_array_type (pkl_ast ast, pkl_ast_node etype, pkl_ast_node
bound)
- | {
- | ...
- | /* The closure slots are GC roots. */
- | pvm_alloc_add_gc_roots (&PKL_AST_TYPE_A_MAPPER (type), 1);
- | pvm_alloc_add_gc_roots (&PKL_AST_TYPE_A_WRITER (type), 1);
- | pvm_alloc_add_gc_roots (&PKL_AST_TYPE_A_BOUNDER (type), 1);
- | ...
- | }
- `----
-
- And of course, before the memory of the AST node is freed, these roots
- should be unregistered from the GC. The right place to do this is in
- `pkl_ast_node_free':
-
- ,----
- | void
- | pkl_ast_node_free (pkl_ast_node ast)
- | {
- | ...
- | case PKL_AST_TYPE:
- | switch (PKL_AST_TYPE_CODE (ast))
- | {
- | ...
- | case PKL_TYPE_ARRAY:
- | /* Remove GC roots. */
- | pvm_alloc_remove_gc_roots (&PKL_AST_TYPE_A_MAPPER (ast), 1);
- | pvm_alloc_remove_gc_roots (&PKL_AST_TYPE_A_WRITER (ast), 1);
- | pvm_alloc_remove_gc_roots (&PKL_AST_TYPE_A_BOUNDER (ast), 1);
- | }
- | }
- `----
-
- So if you add PVM values or PVM environments to an AST node, please
- follow the strategy above.
-
-
-14 Terminal Handling
-====================
-
-14.1 pk-term
-~~~~~~~~~~~~
-
- Writing to the terminal, and getting information from the terminal, is
- handled by the `pk-term' module. It provides functions to:
-
- - Write strings to the standard output.
-
- - Write formatted strings to the standard output, ala `printf'.
-
- - Handle output "classes", which are the base of styling.
-
- Out terminal abstraction is implemented of top of GNU libtextstyle.
- In case it is not available when building poke, a dummy stub is
- provided by gnulib. In that case output won't be styled, but poke
- will still compile and run properly.
-
-
-14.2 Styling Classes
-~~~~~~~~~~~~~~~~~~~~
-
- Styling is handled using "classes", which are identified by some
- string. Using `pk_term' calls, enclosed environments can be defined:
-
- ,----
- | pk_term_class ("foo");
- | /* Text emitted here has class "foo" */
- | pk_term_class ("bar");
- | /* Text emitted here has class "foo" and "bar" */
- | pk_term_end_class ("bar");
- | pk_term_end_class ("foo");
- `----
-
-
- The `class' and `end_class' calls should be properly paired.
-
- The styling classes used in poke should be documented in the user
- manual, so the user will know what is suitable to be configured.
- Also, whenever possible a reasonable default shall be provided in
- `poke-default.css'.
-
-
-14.3 Debugging Styling
-~~~~~~~~~~~~~~~~~~~~~~
-
- As recommended in the libtextstyle manual, a good way to see the class
- hierarchy of some given output is to run poke passing the
- `--color=html' option:
-
- ,----
- | $ poke --color=html
- | [...]
- | (poke) [1#B,2#B]
- | <span class="array">[<span class="offset"><span
class="integer">0x1</span>#B</span>,<span class="offset"><span
class="integer">0x2</span>#B</span>]</span><br/>(poke)
- `----
-
-
-15 Debugging poke
-=================
-
-15.1 Building with Debugging support
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Short summary: at the present time Poke and its Jittery VM are not
- especially difficult to debug; however the situation is going to
- change as Jitter evolves and the following details will become more
- important to Poke hackers.
-
- In order to make debugging easier you may want to disable advanced
- dispatches in Jitter, which make the generated code harder to follow
- and confuse GDB.
-
- Jitter by default will use the most efficient dispatch which is both
- stable and available for the current configuration. The remark about
- stability is important: at the time of writing there are still bugs in
- the two most advanced dispatching modes, `minimal-threading' and
- `no-threading', which may result in subtly incorrect compiled code.
- For this reason Jitter disables those dispatches by default; they will
- be re-enabled in Jitter as soon as they are deemed ready for
- production use, at which point Poke will make use of them
- automatically.
-
- Jitter supports two alternative dispatches, slower but very stable and
- friendly to debugging: `switch' and `direct-threading'.
-
- Any dispatch can be selectively enabled or disabled from the Poke
- `configure' script, by passing the following options which will be
- automatically relayed to Jitter's `configure' script:
-
- - `--enable-dispatch-switch'
- - `--disable-dispatch-switch'
- - `--enable-dispatch-direct-threading'
- - `--disable-dispatch-direct-threading'
- - `--enable-dispatch-minimal-threading'
- - `--disable-dispatch-minimal-threading'
- - --enable-dispatch-no-threading=
- - `--disable-dispatch-no-threading'
-
- When configured in sub-package mode, as is the case when used with
- Poke, Jitter will only actually compile the single most efficient
- enabled dispatch.
-
-
-15.2 Invoking GDB to debug an uninstalled poke
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Since we are using libtool, `$(builddir)/poke/poke' is a shell script.
- In order to debug the uninstalled poke, you can do:
-
- ,----
- | $ ./libtool --mode=execute ./run gdb poke/poke
- `----
-
-
-15.3 Using GDB extensions
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
- In order to use the GDB pretty-printers and other goodies brought to
- you courtesy of the poke hackers, just source the poke-gdb.scm file
- from your debugger:
-
- ,----
- | (gdb) source etc/poke-gdb.scm
- `----
-
-
-15.4 Valgrind and Poke
-~~~~~~~~~~~~~~~~~~~~~~
-
- The PVM uses the Boehm conservative garbage collector in order to
- manage the memory used by the VM values. Other parts of poke, such as
- the PKL compiler, manage their own memory.
-
- Valgrind gets easily confused by the GCs tampering with the stack, and
- emits a lot of spurious warnings. Fortunately it is possible to tell
- memcheck to omit these warnings: the file etc/boehm-gc.suppresions
- contains a list of suppressions.
-
- Invoke valgrind with `--suppressions=etc/boehm-gc.suppressions'.
-
- If despite using the suppressions file you see some spurious warning,
- please use:
-
- ,----
- | $ valgrind --tool=memcheck --gen-suppressions=all --log-file=raw.log
- `----
-
-
- Then process raw.log with the `etc/parse-valgrind-suppressions.sh'
- script, wildcard the result as much as you can, and append the results
- to `etc/boehm-gc.suppressions'.
-
- In order to run the testsuite with valgrind, edit `lib/poke-dg.exp'
- and uncomment the lines:
-
- ,----
- | set VALGRIND "valgrind --quiet \
- | --suppressions=${srcdir}/../etc/boehm-gc.suppressions \
- | --tool=memcheck --gen-suppressions=all"
- `----
-
-
- Then run `make check' as usual.
-
-
-15.5 Debugging PVM Assembly Code
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Hacking some areas of the compiler, such as the code generator pass,
- involves meta-programming PVM assembler. It is easy to find examples
- anywhere in `libpoke/pkl-gen.c':
-
- ,----
- | pkl_asm_insn (pasm, PKL_INSN_ROT);
- | pkl_asm_insn (pasm, PKL_INSN_MULLU);
- | pkl_asm_insn (pasm, PKL_INSN_NIP2);
- `----
-
-
- Or, alternatively, the code may be written in RAS in a `.pks' file.
- Like:
-
- ,----
- | .loop:
- | bz @type, .endloop ; ... A B
- | mod @type ; ... A B A%B
- | rot ; ... B A%B A
- | drop ; ... B A%B
- | ba .loop
- `----
-
-
- Often, a run-time problem becomes apparent while the PVM executes the
- generated code. Typical cases are when a PVM value doesn't contain
- what it's supposed to contain, and accessing the wrong boxed value
- causes a segmentation fault (if we are lucky) or a non-crashing
- invalid memory access (if we are very unlucky.) Whenever that kind of
- crap happens, we find ourselves in the need of debugging the PVM code,
- which is a big PITA.
-
- Bad news are: we don't have a PVM debugger (yet). Good news are: we
- have a couple of tools that may help.
-
- The first of such tools is the `prints' instruction. This
- instructions basically prints in the standard output the string value
- on the TOS, and then drops it. It is a wonderful way to trace PVM
- code.
-
- For example, let's say we are trying to find out how many times the
- loop above gets executed. We can install traces like:
-
-
- ,----
- | push "XXX entering loop\n"
- | prints
- | .loop:
- | push "XXX in loop\n"
- | prints
- | mod @type
- | rot
- | drop
- | ba .loop
- `----
-
-
- The other tool is the `strace' instruction. It prints the contents of
- the stack (one value per line) from the TOS. It gets the number of
- stack values to print as an argument, 0 meaning all of them. It is
- very useful in many situations, like when a loop is composing values
- in the stack and something is going banana. It is also useful to
- determine what kind of value is being accessed by a given instruction.
-
- For example, lets say that we are hunting some segmentation fault. We
- highly suspect the code generated in the first example in this
- section, above. Of the three instructions, `mullu' is the only one
- that could conceivably generate a segfault, so we add a stack trace
- instruction right before it to inspect its two arguments:
-
- ,----
- | pkl_asm_insn (pasm, PKL_INSN_ROT);
- | pkl_asm_insn (pasm, PKL_INSN_STRACE, 2); /* XXX remove me */
- | pkl_asm_insn (pasm, PKL_INSN_MULLU);
- | pkl_asm_insn (pasm, PKL_INSN_NIP2);
- `----
-
-
- We recompile, re-run, and we find out that the elements at the TOS
- when `mullu' is executed are a pair of stupid signed integers, which
- are not boxed and not what the instruction expects. Mystery solved.
-
-
-16 Profiling poke
-=================
-
-16.1 Building with profiling support
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- poke supports a couple of commands that can be used to profile Poke
- programs:
-
- ,----
- | .vm profile reset
- | .vm profile show
- `----
-
-
- For these commands to work you need to build poke with profiling
- support. This is done by passing the `--enable-pvm-profiling' command
- line option to `configure'.
--
2.30.0
- [PATCH 1/2] Fix typo for PKG_CONFIG_PATH,
Guillermo E. Martinez <=