Tools for Meta-Programming - Presentation Transcript
Tools for Meta-Programming
Paul Feautrier
Paul.Feautrier@ens-lyon.fr.
ENS Lyon
Dagsthul-2003 – 1/22
What is Metaprogramming?
Writing programs acting on other programs.
All compilers do metaprogramming.
Generative programming, Skeleton programming, Domain
Specific Optimization, Partial Evaluation, Specialization etc. are
instances of metaprogramming.
Dagsthul-2003 – 2/22
Why Metaprogramming?
Compilers and other elements of the program generation chain
were created to lighten the burden of programming.
This idea has had so much success that every user community
wants its own programming language or system.
Building a compiler is difficult and time consuming. Economically,
it can only be considered if the user base is very large.
Domain specific languages must be built using simpler tools and
should reuse existing software as much as possible.
Dagsthul-2003 – 3/22
Is Metaprogramming Different?
In metaprogramming, the emphasis is on composition of
programs from large pieces.
Compilers do this too, but with much smaller components.
Part of the job of a compiler (e.g. machine code generation) is
irrelevant to metaprogramming. Metaprogramming systems
should work source-to-source and be as much machine
independent as possibe.
Warning: some optimizations cannot be expressed at the source
level: consider for instance array bound checking in the JVM.
Dagsthul-2003 – 4/22
Who is metaprogramming?
Today, a few hundreds of compiler writers.
Tomorrow, a few thousand domain specific experts.
In a few years, every programmer will want to do
metaprogramming.
Dagsthul-2003 – 5/22
Tools Wanted!
Writing a compiler is a highly specialized task: you just have to
weight recent books on the subject to get a feeling!
Compare with Parallel Programming: it was not accepted until
tools for writing parallel programs (e.g. the MPI library) where
designed.
Similarly, tools are needed for enabling metaprogramming.
Dagsthul-2003 – 6/22
State of the Art
Lexer and Parser Generators
Code Generation Generators
The C preprocessor
Tree Rewriting Systems
C++ Templates
Polytopes Tools
Dagsthul-2003 – 7/22
The C preprocessor
Probably the oldest metaprogramming system.
Macros (user defined rewrite rules) with the #define
pseudo-instruction.
Program generation via the #include pseudo-instruction.
However, no way of checking that the result of the composition is
legal.
Conditional compilation via the #if #else #endif
construction.
The power of the system is limited, because redefining a macro is
not allowed. Hence, recursion is possible but will never succeeds.
Dagsthul-2003 – 8/22
C++ Templates
Templates in C++ were designed to write parametric classes, the
parameters being types.
A template class can be instantiated by supplying actual values
for type parameters.
The notation for instantiation is similar to function application.
This is typical meta-programming:
A template class is a data object which represents a whole family of
programs.
Instantiating the template is a computation (substitution of names by values),
which builds one of the programs in the family.
Template programming is difficult and is usually left to experts,
but is much easier than writing a compiler!
Similar mechanisms exist in other languages: e.g. the functors in
Ocaml.
Dagsthul-2003 – 10/22
C++ Templates, II
The template instanciation mechanism is more or less equivalent
to -reduction in -calculus. Hence, a C++ compiler has Turing
power and templates can be used as a GP language!
But as a metaprogramming device, templates are quite limited.
A function cannot be a parameter of a template; consider a
generic sorting routine in which the comparison function is a
parameter.
Dagsthul-2003 – 11/22
Z-Polyhedra: How and Why
A Z-polyhedron is the set of integer solutions to a system of linear
inequalities.
Z-Polyhedra are a convenient model for loops and arrays.
Used for checking program correctness, finding parallelism,
optimizing locality.
Range: so-called regular programs only.
Drawback: they give specifications for program transformations,
but not the result of the transformation.
Dagsthul-2003 – 12/22
Tools for Polyhedra
In many cases, a Z-polyhedron can be approximated by the
enclosing polyhedron. Hence, two types of tools: rational and
integral solvers.
The master problem: deciding if a Z-polyhedron is empty or not.
Omega: rational and integral, handles Pressburger logic.
Pip: rational and integral, handles parametric problems.
the Polylib: rational. Extension for counting the integer points in a
polyhedron.
Cloog: Constructing loop nests from polyhedra; based on an
algorithm by F. Quilleré.
Dagsthul-2003 – 13/22
Some Proposals
Dagsthul-2003 – 14/22
Overview
What are the components of a metaprogramming tool?
There must be a representation for programs and program
pieces.
There must be methods for building and transforming programs.
Program transformations are not universally applicable. There
must be methods for analyzing a program, the aim being to
decide whether a transformation is applicable or not.
Lastly, there must be a way of driving the metaprogramming
process.
Dagsthul-2003 – 15/22
A Menagerie of Data Structures
Abstract Syntax Tree
Control Graph
Call Graph
Dependence Graph(s)
Symbol Tables
Polyhedra for iteration domains, dependences, schedules, ...
Each method for building, analysing or transforming programs has a
preferred data structure. Examples:
Parsing, dependence analysis, code generation are best done on the AST.
Some forms of dataflow analysis prefer the Control Graph and/or the Call Graph.
Parallelization uses both the AST and the dependence graph.
Dagsthul-2003 – 16/22
Coherence
One may either use several data structures, converting back and forth
as needed, or try to define a kind of lowest common multiple.
If the program is transformed, all data structures must be kept
coherent.
E.g. if two loops are exchanged, one must adjust the AST, the
control graph and the dependence graph.
This is best done in a lazy way, whether the implementation
language is lazy or not.
Dagsthul-2003 – 17/22
Is There a Universal Representation?
Denotational semantics is an attempt to represent a program as a
function in the mathematical sense.
The thrust of denotational semantics has been about proving by
hand properties of programming languages and programs.
However, denotational equations can be represented as formulas
(e.g. inside a computer algebra system).
Program building is done by a system of combinators on these
functions. E.g. the sequence is represented by function
composition.
Program transformations, optimizations, specialization are
equational reasoning on the definition of the semantical functions.
One drawback: Denotational Semantics is not well suited for
parallel programs.
Dagsthul-2003 – 18/22
Program Analysis
The results of program analysis are in the form of assertions, not
equations.
For instance, saying that a variable is of type asserts that all
¢
values of belong to the carrier of .
¢
There must be a logic for reasoning on these assertions.
However, for efficiency reasons, parts of this logic may be
implemented as special purpose algorithms. Example are:
Type systems, which use efficient algorithms based on unification.
The polytope model, in which linear programming algorithms replace
reasoning on linear inequalities.
Abstract interpretation.
The design of such a partially decidable logic is a difficult
problem.
Dagsthul-2003 – 19/22
Oracles
Many of these analysis tools behave like oracles: they are given a
problem (e.g. testing a dependence) without reference to the
originating program.
Most of these oracles are independent stand alone programs,
which are written in as many programming languages (C, C++,
Java, Ocaml, MuPAD, Mathematica among others).
Talking with oracles is a difficult problem in code coupling.
Since most of these tools have some kind of command language,
one solution is to have the metaprogramming system
communicate with the oracles by sending programs to them.
Dagsthul-2003 – 20/22
The Metalanguage
The metalanguage must be imperative (or else there will be a need for
an imperative meta-meta-language, etc.).
Beside ordinary features, it must have special constructors and
destructors/observers for acting on the program representation.
An equational representation is specially adapted to a lazy
implementation.
One important concept: the focus. At any given time, the
metaprogramming system is considering one particular part of the
program, where properties are examined and transformations are
applied.
There must be provisions for moving the focus around according to the
results of previous investigations.
There may be several unrelated focuses (handy for moving information
around), or a hierarchy of focuses (a procedure, a statement and a
variable).
Dagsthul-2003 – 21/22
Future Work
Specify a concrete representation for denotational semantics.
Investigate extensions for parallel programs (parallel programs as
relations, operational semantics, powerset, execution orders?).
Specify constructors and observers.
Start playing with the system by hand. Try to reproduce well
known metaprogramming operations (e.g. partial evaluation).
Design a way of communicating with oracles.
Design the metalanguage.
Dagsthul-2003 – 22/22
0 comments
Post a comment