Modula-2 Reloaded

A Modern Typesafe & Literate Programming Notation

Site Menu

Project

Specification

Implementation

Recommendations

Reference

Needs Updating

Work in Progress

Wastebasket

Wiki Manual

edit SideBar

Template Based Generics

WiP.TemplateBasedGenerics History

Hide minor edits - Show changes to output

2010-01-26 00:11 by benjk -
Changed lines 30-31 from:
[@<* BUILD=(information for make goes here) *>@]
to:
[@<* MAKE=(information for make goes here) *>@]
Changed lines 40-41 from:
[@<*BUILD=(template:stack, license:"@@BSD@@", module:"CardinalStack", type:"CARDINAL") *>
to:
[@<*MAKE="expand(template:stack, license:"@@BSD@@", module:"CardinalStack", type:"CARDINAL")" *>
Changed line 114 from:
The only addition required to accommodate the above is the [@<*BUILD...*>@] pragma.
to:
The only addition required to accommodate the above is the [@<*MAKE...*>@] pragma.
2010-01-17 07:12 by benjk -
Changed line 107 from:
template is expanded and generates the definition part for module `CardinalStack. When the compiler is invoked on the generated source, everything will be type checked by the compiler in the same way as usual. The compiler does not have any knowledge about the fact that the module was made from a template. The debugger does not need to know either, nor does the human reader of the resulting output when examining the program.
to:
template is expanded and generates the definition part for module `CardinalStack. When the compiler is invoked on the generated source, the source will be type checked by the compiler in the same way as usual. The compiler does not have, nor does it need to have any knowledge about the fact that the module was generated from a template. The debugger does not need to know either, nor does the human reader of the resulting output when examining the program.
2010-01-17 07:06 by benjk -
Changed line 34 from:
The above is entirely sufficient to implement template based generics that are fully integrated into the build process, that is to say, not requiring the human user to expand templates manually. At the same time, a human user could '''choose''' to expand templates manually if he wished to do so.
to:
The above is entirely sufficient to implement template based generics that are fully integrated into the build process, that is to say, not requiring the human user to expand templates manually. At the same time, a human user could '''choose''' to expand templates manually if he or she wished to do so.
2010-01-17 07:05 by benjk -
Changed line 24 from:
In order for a make utility or make script to know when to expand templates into compilable source and what translations for the placeholders need to be passed to the template engine, there would either have to be a configuration file or the information would have to be embedded in those source files that import the expanded source.
to:
In order for a make utility or make script to know when to expand templates into compilable source and what translations for the placeholders need to be passed to the template engine, there would either have to be a configuration file or the information would have to be embedded in the definition part source files that import the expanded source files.
2010-01-09 13:34 by benjk -
Changed line 40 from:
[@<*BUILD=(template:stack, license:"BSD", module:"CardinalStack", type:"CARDINAL") *>
to:
[@<*BUILD=(template:stack, license:"@@BSD@@", module:"CardinalStack", type:"CARDINAL") *>
2010-01-09 13:14 by benjk -
Changed line 36 from:
!!An Example
to:
!!!An Example
Changed line 62 from:
!!!Driving the Build Process
to:
!!!!Driving the Build Process
Changed line 69 from:
!!!The Template
to:
!!!!The Template
Changed line 105 from:
!!!Expanding the Template
to:
!!!!Expanding the Template
Changed line 111 from:
!!!Conclusion
to:
!!!!Conclusion
2010-01-09 13:11 by benjk -
Deleted line 7:
Deleted line 23:
Changed line 62 from:
!!!The Build Process
to:
!!!Driving the Build Process
Added line 105:
!!!Expanding the Template
Added line 111:
!!!Conclusion
2010-01-09 13:07 by benjk - headings
Changed lines 34-37 from:
The compiler would ignore this pragma. Its content is only to be understood by the make utility. The delimiters for the actual
information could be chosen differently if for some reason parentheses seem
unsuitable.

to:
The compiler would ignore the body of this pragma. Its content is only to be understood by the make utility. The delimiters for the actual information could be chosen differently if for some reason parentheses seem unsuitable.
Changed line 38 from:
to:
!!An Example
Changed line 41 from:
to:
!!!Client Program Using a Template Derived Module
Changed line 64 from:
to:
!!!The Build Process
Added line 71:
!!!The Template
2010-01-09 13:00 by benjk -
Changed line 13 from:
It takes any text file which contains placeholders tagged with leading and trailing "@@" tags and recursively replaces those placeholders with their translations, copying them into the output file.
to:
This template engine takes any input text which contains placeholders tagged with leading and trailing "@@" tags and recursively replaces those placeholders with their translations, copying them into the output text.
2010-01-09 12:59 by benjk -
Changed line 9 from:
A simple template engine utility (about 350 lines of code) is available at:
to:
A suitable template engine utility (about 350 lines of code) is available at Benjamin's private repository:
2010-01-09 12:58 by benjk - formatting
Changed line 26 from:
As for #2, in order for a make utility or make script to know when to expand templates into compilable source and what translations for the placeholders need to be passed to the template engine, there would either have to be a configuration file or the information would have to be embedded in those source files that import the expanded source.
to:
In order for a make utility or make script to know when to expand templates into compilable source and what translations for the placeholders need to be passed to the template engine, there would either have to be a configuration file or the information would have to be embedded in those source files that import the expanded source.
2010-01-09 12:56 by benjk - formatting
Changed lines 9-11 from:
As for #1, a simple template engine utility (about 350 lines of code) is available at:

[[http://bitbucket.org/trijezdci/ctelib/src/]]
to:
A simple template engine utility (about 350 lines of code) is available at:

*[[http://bitbucket.org/trijezdci/ctelib/src/]]
2010-01-09 12:55 by benjk - formatting
Changed lines 5-7 from:
1) a text template engine that can expand templates with placeholders into compilable source

2) a make utility or make script that can determine when a template needs to be expanded before compilation
to:
* a text template engine that can expand templates with placeholders into compilable source
* a make utility or make script that can determine when a template needs to be expanded before compilation
2010-01-09 12:45 by benjk -
Changed line 112 from:
The tags [@%%@] and @@ tags are not part of the language for which the templates are used to generate output for. They are understood by the template engine utility only. The tags could easily be changed if desired.
to:
The tags [@%%@] and @@ are not part of the language for which the templates are used to generate output for. They are understood by the template engine utility only. The tags could easily be changed if desired.
2010-01-09 12:45 by benjk - formatting
Changed line 112 from:
The tags %% and @@ tags are not part of the language for which the templates are used to generate output for. They are understood by the template engine utility only. The tags could easily be changed if desired.
to:
The tags [@%%@] and @@ tags are not part of the language for which the templates are used to generate output for. They are understood by the template engine utility only. The tags could easily be changed if desired.
2010-01-09 12:43 by benjk - minor style edits
Changed lines 110-112 from:
template is expanded and generates the definition part for module `CardinalStack. When the compiler is invoked on the generated source, everything will be type checked by the compiler in the same way as usual. The compiler does not have any knowledge about the fact that the module was made from a template. The debugger doesn't need to know either. Nor does the human reader of the resulting output when examining the program.

The tags %% and @@ tags are not part of the language for which the templates are used to generate output for. They are understood by the template engine utility only.
to:
template is expanded and generates the definition part for module `CardinalStack. When the compiler is invoked on the generated source, everything will be type checked by the compiler in the same way as usual. The compiler does not have any knowledge about the fact that the module was made from a template. The debugger does not need to know either, nor does the human reader of the resulting output when examining the program.

The tags %% and @@ tags are not part of the language for which the templates are used to generate output for. They are understood by the template engine utility only. The tags could easily be changed if desired.
2010-01-09 12:40 by benjk - formatting
Changed line 76 from:
NB: The CTE template engine recognises %% at the beginning of a line as a template comment which it does not copy into the output.
to:
NB: The CTE template engine recognises [@%%@] at the beginning of a line as a template comment which it does not copy into the output.
2010-01-09 12:39 by benjk - minor style edits
Changed lines 70-71 from:
If the compiler is the driver, it would recognise the [@<*BUILD...*>@] pragma and invoke the make utility, passing the entire string between ( and ) to the make utility. The make utility would then use the information to generate the `CardinalStack module (both definition and implementation parts) by invoking the template engine utility with the required parameters as provided in the pragma body. When the make utility is done, the compiler would continue to compile module `UseCardinalStack. If the [@<*BUILD...*>@] pragma is missing, then the compiler would generate an error that module `CardinalStack could not be found.
to:
If the compiler is the driver, it would recognise the [@<*BUILD...*>@] pragma and invoke the make utility, passing the pragma and its body to the make utility. The make utility would then use the information to generate the `CardinalStack module (both definition and implementation parts) by invoking the template engine utility with the required parameters as provided in the pragma body. When the make utility is done, the compiler would continue to compile module `UseCardinalStack. If the [@<*BUILD...*>@] pragma is missing, then the compiler would generate an error that module `CardinalStack could not be found.
Changed line 76 from:
NB: The CTE library recognises %% at the beginning of a line as a template comment which is not copied into the output by the template engine.
to:
NB: The CTE template engine recognises %% at the beginning of a line as a template comment which it does not copy into the output.
2010-01-09 12:34 by benjk - added license templating example
Changed lines 45-46 from:
[@<*BUILD=(template:stack, module:"CardinalStack", type:"CARDINAL") *>
to:
[@<*BUILD=(template:stack, license:"BSD", module:"CardinalStack", type:"CARDINAL") *>
Added line 86:
Changed lines 88-92 from:
   For license see LICENSE file.
to:

  License:

  @@license@@

2010-01-09 12:23 by benjk - formatting
Changed line 97 from:
     VAR status : Status);
to:
         VAR status : Status);
2010-01-09 12:23 by benjk - formatting
Changed lines 96-97 from:
                            value : @@type@@;
             
      VAR status : Status);
to:
               value : @@type@@;
      VAR status : Status);
2010-01-09 12:21 by benjk - formatting
Changed lines 96-97 from:
                                  value : @@type@@;
                       VAR status : Status);
to:
                             value : @@type@@;
                    VAR status : Status);
2010-01-09 11:45 by benjk - formatting
Changed lines 10-11 from:
As for #1, a simple utility (about 350 lines of code) is available at:
to:
As for #1, a simple template engine utility (about 350 lines of code) is available at:
Added line 54:
Added line 56:
Added line 58:
Added line 60:
Added line 62:
Added line 64:
Changed lines 70-80 from:
If the compiler is the driver, it would recognise the <*BUILD...*> pragma and invoke the make utility, passing the entire string between ( and ) to the make utility. The make utility would then use the information to generate the CardinalStack module (both definition and implementation parts) by invoking the template engine utility with the required parameters as provided in the pragma body. When the make utility is done, the compiler would continue to compile module UseCardinalStack. If the <*BUILD...*> pragma is missing, then the compiler would generate an error that module CardinalStack could not be found.

If the make utility is the driver, it would first scan the source code for any occurrences of the <*BUILD...*> pragma. When it encounters the pragma it would generate the respective modules by invoking the template engine utility with the placeholder translations as given in the bodies of the respective <*BUILD...*> pragmas.

An example of a template to generate the CardinalStack definition part is given below:

[@NB: The CTE library recognises %% at the beginning of a line as a
template comment which is not copied into the output by the template
engine.

%% Template to generate definition modules for stacks in Modula-2
to:
If the compiler is the driver, it would recognise the [@<*BUILD...*>@] pragma and invoke the make utility, passing the entire string between ( and ) to the make utility. The make utility would then use the information to generate the `CardinalStack module (both definition and implementation parts) by invoking the template engine utility with the required parameters as provided in the pragma body. When the make utility is done, the compiler would continue to compile module `UseCardinalStack. If the [@<*BUILD...*>@] pragma is missing, then the compiler would generate an error that module `CardinalStack could not be found.

If the make utility is the driver, it would first scan the source code for any occurrences of the [@<*BUILD...*>@] pragma. When it encounters the pragma it would generate the respective modules by invoking the template engine utility with the placeholder translations as given in the bodies of the respective [@<*BUILD...*>@] pragmas.

An example of a template to generate the `CardinalStack definition part is given below:

NB: The CTE library recognises %% at the beginning of a line as a template comment which is not copied into the output by the template engine.

[@%% Template to generate definition modules for stacks in Modula-2
Changed lines 83-84 from:
%% -  type : the identifier of the base type for values to be stored
in the stack
to:
%% -  type : the identifier of the base type for values to be stored in the stack
Changed lines 89-90 from:
DEFINITION MODULE @@module@@Stack;
to:
DEFINITION MODULE @@module@@;
Changed lines 105-106 from:
template is expanded and generates the definition part for module CardinalStack. When the compiler is invoked on the generated source, everything will be type checked by the compiler in the same way as usual. The compiler does not have any knowledge about the fact that the module was made from a template. The debugger doesn't need to know either. Nor does the human reader of the resulting output when examining the program.
to:
template is expanded and generates the definition part for module `CardinalStack. When the compiler is invoked on the generated source, everything will be type checked by the compiler in the same way as usual. The compiler does not have any knowledge about the fact that the module was made from a template. The debugger doesn't need to know either. Nor does the human reader of the resulting output when examining the program.
Changed line 111 from:
The only addition required to accommodate the above is the <*BUILD...*> pragma.
to:
The only addition required to accommodate the above is the [@<*BUILD...*>@] pragma.
2010-01-09 11:40 by benjk - formatting
Changed line 18 from:
''"Dear @@@@title@@@@ @@@@name@@@@,"''
to:
''"Dear [@@@title@@@] [@@@name@@@],"''
2010-01-09 10:31 by benjk - formatting
Added line 6:
Changed line 18 from:
''"Dear @@title@@ @@name@@,"''
to:
''"Dear @@@@title@@@@ @@@@name@@@@,"''
2010-01-09 10:31 by benjk - new page describing a model for generics
Added lines 1-111:
The following describes a method to support template based generics outside of the language definition.

The basic principle is to let the build system take care of template expansion and hide this process from the compiler altogether. In order to do this, two external utilities are required:

1) a text template engine that can expand templates with placeholders into compilable source
2) a make utility or make script that can determine when a template needs to be expanded before compilation


As for #1, a simple utility (about 350 lines of code) is available at:

[[http://bitbucket.org/trijezdci/ctelib/src/]]

It takes any text file which contains placeholders tagged with leading and trailing "@@" tags and recursively replaces those placeholders with their translations, copying them into the output file.

For example, the template ...

''"Dear @@title@@ @@name@@,"''

using the translations title="Mr." and name="Sutcliffe" is expanded into ...

''"Dear Mr. Sutcliffe,"''

This can be used to expand placeholders in source code templates to generate compilable source.


As for #2, in order for a make utility or make script to know when to expand templates into compilable source and what translations for the placeholders need to be passed to the template engine, there would either have to be a configuration file or the information would have to be embedded in those source files that import the expanded source.

A configuration file would have to be created by the user of a library separately from the actual source files for which the expanded source is produced. This would then require three different files to be maintained per module: a configuration file for the make utility, the definition part and the implementation part. This is not as user friendly as it could and should be.

Embedding the information that the make utility needs directly into the source code can be easily accommodated by an additional pragma, for instance

[@<* BUILD=(information for make goes here) *>@]

The compiler would ignore this pragma. Its content is only to be understood by the make utility. The delimiters for the actual
information could be chosen differently if for some reason parentheses seem unsuitable.


The above is entirely sufficient to implement template based generics that are fully integrated into the build process, that is to say, not requiring the human user to expand templates manually. At the same time, a human user could '''choose''' to expand templates manually if he wished to do so.


The following is a concrete example of a generic stack template and its use in a Modula-2 program:


[@<*BUILD=(template:stack, module:"CardinalStack", type:"CARDINAL") *>

MODULE UseCardinalStack;

IMPORT CardinalStack; (* generated by make utility from template *)

VAR
  stack : CardinalStack.Stack;
  num : CARDINAL;
...
CardinalStack.push(stack, num, NIL);
...
num = CardinalStack.pop(stack, NIL);
...
END UseCardinalStack.@]


There are two principle ways in which a project could then be built. Either the compiler is used as the driver program for the build or the make utility is used as the driver program for the build.

If the compiler is the driver, it would recognise the <*BUILD...*> pragma and invoke the make utility, passing the entire string between ( and ) to the make utility. The make utility would then use the information to generate the CardinalStack module (both definition and implementation parts) by invoking the template engine utility with the required parameters as provided in the pragma body. When the make utility is done, the compiler would continue to compile module UseCardinalStack. If the <*BUILD...*> pragma is missing, then the compiler would generate an error that module CardinalStack could not be found.

If the make utility is the driver, it would first scan the source code for any occurrences of the <*BUILD...*> pragma. When it encounters the pragma it would generate the respective modules by invoking the template engine utility with the placeholder translations as given in the bodies of the respective <*BUILD...*> pragmas.

An example of a template to generate the CardinalStack definition part is given below:

[@NB: The CTE library recognises %% at the beginning of a line as a
template comment which is not copied into the output by the template
engine.

%% Template to generate definition modules for stacks in Modula-2
%%
%% requires translations for the following placeholders:
%%
%% -  module : the identifier of the generated module
%% -  type : the identifier of the base type for values to be stored
in the stack
%%
(* Stack module for @@type@@ derived from template stack
  Copyright (c) 2010 Jon Doe (template author).
  For license see LICENSE file.
*)
DEFINITION MODULE @@module@@Stack;

TYPE Stack = OPAQUE;

PROCEDURE new(VAR status : Status) : Stack;

PROCEDURE push(stack : Stack;
                                  value : @@type@@;
                        VAR status : Status);
...

END @@module@@;
%%
%% End of template stack@]

By invoking the template engine utility with a path to the stack template and placeholder translations for 'module' and 'type' the
template is expanded and generates the definition part for module CardinalStack. When the compiler is invoked on the generated source, everything will be type checked by the compiler in the same way as usual. The compiler does not have any knowledge about the fact that the module was made from a template. The debugger doesn't need to know either. Nor does the human reader of the resulting output when examining the program.

The tags %% and @@ tags are not part of the language for which the templates are used to generate output for. They are understood by the template engine utility only.

The template expansion can be done right now with the CTE library as it is, no modifications required. The autotools and Cmake build systems could be relatively easily scripted/configured to control the build process in the way described above, again without making modifications to the source code of their respective make utilities.

The only addition required to accommodate the above is the <*BUILD...*> pragma.

The language itself does not need any modifications. No complexity is added to any of compiler, linker, debugger.

In the context of education, it would seem that making the template expansion process explicit and transparent should be a benefit to understanding the code and its translation process. The issue becomes another case of "eliminating magic".