Somusar/Tefigel[tm]

A Tutorial Introduction

Francesco Aliverti-Piuri

Copyright © 2003-2007 Somusar

      
      
      
      
      
      
      
      
      
      
      
      
      
      

Copyright © 2003-2007 so.mus.ar. s.a.s.
Via Sangallo 30 - 20133 Milan - Italy
All rights reserved.

Unix is a registered trademark in the United States and other countries, licensed exclusively through X/Open Company Limited.

Linux is a registered trademark of Linus Torvalds in the United States and other countries.

Sun, Sun Microsystems, the Sun logo, Solaris, Java, and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.

Symbian and all Symbian-based marks and logos are trademarks of Symbian Software Limited.

Apple and Mac OS are registered trademarks of Apple Computer, Inc. in the United States and other countries.

Intel is a registered trademark of Intel Corporation in the United States and other countries.

PowerPC and CICS are registered trademarks of International Business Machines Corporation in the United States and other countries.

Microsoft, Windows, Visual Basic are either trademarks or registered trademarks of Microsoft Corp. in the United States and/or other countries.

Oracle is a registered trademark, and PL/SQL is a trademark of Oracle Corporation.

SAP and ABAP/4 are registered trademarks of SAP AG in Germany and several other countries.

PostScript is a registered trademark of Adobe Systems Incorporated in the United States and/or other countries.

So.mus.ar, the Somusar logo, Somusar/Software Production Technique, Somusar/Software Production Machine, Somusar/Sisendel, Somusar/Tefigel, Somusar/SoProTech, Somusar/SoProMach, Somusar/Software Entity, Somusar/Software Mold, Somusar/Software Mold Kit, Somusar/Software Mold Building, Somusar/Code Generator Building, Somusar/Generator Building, and Somusar/File Generation Scheme are trademarks of so.mus.ar. s.a.s. in Italy, in the European Union, in the United States of America and other countries.

Other trademarks or service marks referenced herein are property of their respective owners.


Contents
Chapter 1 - Introduction
Chapter 2 - Language Summary
Chapter 3 - Text File Components
3.1 - Text Files and Text Lines
3.2 - Commands and Instructions
3.3 - Comments
3.4 - Markers
3.5 - Special Characters
3.6 - Variables
3.7 - Name Spaces
Chapter 4 - Text File Processing
4.1 - Arithmetic Computation
4.2 - Control Flow and Boolean Computation
4.3 - Input and Output
Chapter 5 - Modularity
5.1 - Subroutines and Functions
5.2 - Packages and Libraries
5.3 - Filters
Chapter 6 - Multilanguage Applicability
Chapter 7 - Generating Object-oriented Languages
7.1 - Java[tm]
7.2 - C#
7.3 - C++
Chapter 8 - Generating Internet-oriented Languages and Protocols
8.1 - HTML
8.2 - XML
8.3 - SOAP
8.4 - PHP
Chapter 9 - Generating Procedural Languages
9.1 - C
9.2 - Visual Basic®
9.3 - COBOL
9.4 - RPG
Chapter 10 - Generating Scripting or Special-purpose Languages
10.1 - SQL
10.2 - Perl
10.3 - Python
10.4 - REXX
10.5 - LaTeX
Chapter 11 - Advanced Features and Topics
11.1 - Tefigel and Sisendel
11.2 - Multilevel Contents Association
11.3 - Data Translation Filters
Chapter 12 - A More Extensive Example
12.1 - The Input List: An Instruction Set
12.2 - List Filters
12.3 - Generated Java[tm] and C Code
Chapter 13 - Further Reading

Code Examples
Code Example 1 - Hello world
Code Example 2 - Hello world II
Code Example 3 - Commands and variables
Code Example 4 - Comments
Code Example 5 - Markers
Code Example 6 - Special Characters
Code Example 7 - Variables and basic operations
Code Example 8 - String concatenation via DASH
Code Example 9 - Name spaces
Code Example 10 - Arithmetic computation
Code Example 11 - Simple loop
Code Example 12 - Boolean computation and control flow
Code Example 13 - Input and output
Code Example 14 - Generating Java[tm] set/get
Code Example 15 - Subroutine for Java[tm] set/get
Code Example 16 - Call key and built-ins
Code Example 17 - Library of Tefigel packages
Code Example 18 - Filters
Code Example 19 - Filter 1
Code Example 20 - Filter 2
Code Example 21 - Generating Java[tm]
Code Example 22 - Generating C#
Code Example 23 - Generating C++
Code Example 24 - Generating HTML
Code Example 25 - Generating XML
Code Example 26 - Generating SOAP
Code Example 27 - Generating PHP
Code Example 28 - Generating C
Code Example 29 - Generating Visual Basic®
Code Example 30 - Generating COBOL
Code Example 31 - Generating RPG
Code Example 32 - Generating SQL
Code Example 33 - Generating Perl
Code Example 34 - Generating Python
Code Example 35 - Generating REXX
Code Example 36 - Generating LaTeX
Code Example 37 - Contents association via DASH
Code Example 38 - Table filters
Code Example 39 - Table filter 1
Code Example 40 - Table filter 2
Code Example 41 - List filters
Code Example 42 - List filter 1
Code Example 43 - List filter 2

Figures
Figure 1 - Tefigel and Sisendel

Chapter 1 - Introduction

This document is an introduction to the syntax, semantics and usage of Somusar/Tefigel[tm], a computer language and translator specifically designed to efficiently assemble source files for virtually any computer language. As an example, the HTML version of this very document, including all of its code examples, has been assembled using Somusar/Tefigel[tm] - shortly referred to as Tefigel.

Tefigel is a complete stand-alone tool, but its powerful features are particularly useful within the Somusar/Software Production Technique[tm], described in "Somusar/Software Production Technique[tm]: An Introduction ", where Tefigel is used as back-end language.

Main functions of Tefigel are:

Tefigel can be concisely defined as a generalized, versatile file-oriented text and macro processor, that significantly reduces repetitive copy & paste activities during software development projects.

The Somusar/Tefigel[tm] language processor is currently available for the following platforms:

Hereinafter both the Somusar/Tefigel[tm] language and translator are referred to simply as Tefigel. Additional details and the exact definition of the syntax and semantics of Tefigel are provided in "Somusar/Tefigel[tm]: Reference Guide ".

Chapter 2 - Language Summary

Basic elements of Tefigel programs and scripts are text files and text lines, intermixed with Tefigel instructions and comments, and name spaces of string, numeric and boolean variables. In short, for the purpose of this document these elements can be defined as follows:

Traditional programming language constructs, such as control flow and arithmetic and boolean computation instructions, are of course also available in Tefigel. These constructs have been purposely designed and implemented in a very simple form for two reasons:
  1. To keep the set of new things to be learned by new Tefigel users as small as possible, in order to help them be more quickly ready to actually use Tefigel;

  2. To focus Tefigel design and implementation on functions that are more closely related to the main purpose of Tefigel, which consists in enabling the automated, efficient and reliable generation of source code files.

Finally, Tefigel's capabilities include simple constructs to control its input and output flows, enabling the processing of several input files, as well as the production of several output files.

Chapter 3 - Text File Components

The basic unit of work of Tefigel is the text file: the concept of Tefigel program or script is in fact purposely not clearly defined by the language, so that the translator can process any type of text file, independently of its contents and name or suffix. Nevertheless, usual programming concepts like instructions, comments and variables are clearly defined, as explained in the next paragraphs of this chapter.

3.1 - Text Files and Text Lines

Traditionally, the first code example of a computer language has always been a "Hello, world!" program. Tefigel copies most of its input to its output, apart from variables substitution and execution of instructions. Thus, Tefigel allows such a "Hello" program to be written in its simplest form as follows.

Code Example 1 - Hello world

The simplest Somusar/Tefigel[tm] program: the traditional one-line greeting message. No actual processing takes place: input is copied to output.
 
Source code - File "hello_world"
    1      Hello, world!
	       

Output of "/opt/somusar/bin/tefigel hello_world"
    1      Hello, world!
	       

A slightly more complex implementation of this example involves a variable and an instruction, namely ECHO, as follows.

Code Example 2 - Hello world II

Set a variable and write it out with an instruction. Note that contents of variable "greeting" is accessed by simply naming it where required, even between double quotes ".
 
Source code - File "hello_world.2"
    1      @ set greeting=Hello, world!
    2      @ echo greeting
    3      Here it comes once again: greeting, and again: "greeting".
	       

Output of "/opt/somusar/bin/tefigel hello_world.2"
    1      Hello, world!
    2      Here it comes once again: Hello, world!, and again: "Hello, world!".
	       

3.2 - Commands and Instructions

Tefigel commands consist of either lines beginning with a Tefigel instruction (that is, a recognized uppercase word), or lines beginning with the current command marker, as shown in the following example.

Code Example 3 - Commands and variables

Short example introducing command lines, variables and the concept of command marker.
 
Source code - File "plain_cmd"
    1      Text lines, not to be altered by tefigel, as they contain neither
    2      tefigel variables, nor tefigel commands.
    3      @ echo Command line, echo message.
    4      @ set MESSAGE="Hello!"
    5      % echo Not a command line (yet), but contains a variable: MESSAGE.
    6      @ mark CMD %
    7      % echo Now a command line, due to command mark CMD. Variable: MESSAGE.
    8      % unset MESSAGE
    9      % echo After unset, variable MESSAGE is no longer a variable.
   10      % mark CMD
   11      % echo '%' is no longer the command line marker.
   12        Some more text lines, not to be altered by tefigel, as they contain
   13        neither tefigel variables, nor tefigel commands. Note that white
   14        s p a c e s   within text lines     are     left           untouched.    
	       

Output of "/opt/somusar/bin/tefigel plain_cmd"
    1      Text lines, not to be altered by tefigel, as they contain neither
    2      tefigel variables, nor tefigel commands.
    3      Command line, echo message.
    4      % echo Not a command line (yet), but contains a variable: "Hello!".
    5      Now a command line, due to command mark CMD. Variable: "Hello!".
    6      After unset, variable MESSAGE is no longer a variable.
    7      % echo '%' is no longer the command line marker.
    8        Some more text lines, not to be altered by tefigel, as they contain
    9        neither tefigel variables, nor tefigel commands. Note that white
   10        s p a c e s   within text lines     are     left           untouched.    
	       

The variable command marker plays an important role in making Tefigel more widely usable. In fact, several computer languages define a constant command marker, such as # in C/C++ preprocessing, or * in RPG comments, or C in Fortran comments: Tefigel's variable command marker allows Tefigel instructions to be intermixed with, and easily recognizable within, virtually any textual computer language. The default command marker is the character @, but it can be set to any other character, as shown in the previous example.

3.3 - Comments

Tefigel comments can be written in two ways, as the next example shows:

Code Example 4 - Comments

Tefigel comments using instruction REM or a variable comment marker.
 
Source code - File "comments"
    1      ------------ Commenting via default "#" -------------------------------
    2      Plain text before the first comment.
    3      # This is a tefigel comment, and will be ignored
    4      # by the tefigel translator
    5      Plain text after the first comment.
    6      ------------ Commenting via a new comment marker (1: use "|") -------
    7      @ mark rem |
    8      Plain text before the second comment.
    9      | After command mark rem above, lines starting with a |
   10      | are treated as comments.
   11      Plain text after the second comment.
   12      ------------ Commenting via a different comment marker (2: use "%") -------
   13      @ mark rem %
   14      Plain text before the third comment.
   15      % After command mark rem above, lines starting with a %
   16      % are treated as comments.
   17      Plain text after the third comment.
   18      |    Note that lines starting with a | are no longer
   19      |    treated as comments.
	       

Output of "/opt/somusar/bin/tefigel comments"
    1      ------------ Commenting via default "#" -------------------------------
    2      Plain text before the first comment.
    3      Plain text after the first comment.
    4      ------------ Commenting via a new comment marker (1: use "|") -------
    5      Plain text before the second comment.
    6      Plain text after the second comment.
    7      ------------ Commenting via a different comment marker (2: use "%") -------
    8      Plain text before the third comment.
    9      Plain text after the third comment.
   10      |    Note that lines starting with a | are no longer
   11      |    treated as comments.
	       

3.4 - Markers

As shortly introduced above, Tefigel features an enhanced preprocessor-like approach: the first character in an input text line may have a special function, such as being a command or comment marker. The definition of a marker is achieved using instruction MARK, which allows to define several types of markers: beyond commands and comments, also function/subroutine CALLs can be associated with a marker.

Code Example 5 - Markers

Use of Tefigel markers.
 
Source code - File "markers"
    1      @ rem Plain comment
    2      @ echo Plain command with default command marker '@'
    3      @ mark rem |
    4      @ mark CMD %
    5      | Comment with new comment marker '|'
    6      % echo Command with new command marker '%'
    7      Plain text line with placeholder.
    8      % set placeholder=<some text>
    9      Plain text line with placeholder.
	       

Output of "/opt/somusar/bin/tefigel markers"
    1      Plain command with default command marker '@'
    2      Command with new command marker '%'
    3      Plain text line with placeholder.
    4      Plain text line with <some text>.
	       

3.5 - Special Characters

Another dynamic syntax construct of Tefigel consists in its set of special characters, which are special-purpose operators that can be used within normal text lines and dynamically changed using appropriate instructions.

Special characters include a DASH operator - explained in a following paragraph - to concatenate strings and create name-value contents association; a LINEBREAK operator, to split one input logical line across two or more physical lines; a CALLKEY operator, to issue function calls from within text lines; and a few more.

Code Example 6 - Special Characters

Split a logical line on two physical lines, and concatenate strings using the current dash operator.
 
Source code - File "special_chars"
    1      Text on two physical lines %
    2      separated by a '%'
    3      @ linebreak %
    4      Text on two physical lines %
    5      separated by a '%'
    6      -----------
    7      Line with a bro-ken word
    8      @ dash -
    9      Line with a bro-ken word
   10      -----------
	       

Output of "/opt/somusar/bin/tefigel special_chars"
    1      Text on two physical lines %
    2      separated by a '%'
    3      Text on two physical lines separated by a '%'
    4      -----------
    5      Line with a bro-ken word
    6      Line with a broken word
    7      -----------
	       

3.6 - Variables

Tefigel variables are basically placeholders for character strings, although basic arithmetic and boolean operations can be performed on them, if the value that they hold allows such operations. The next example briefly shows how Tefigel variables can be used.

Code Example 7 - Variables and basic operations

Variables can be of different types (strings, numbers and boolean), although they are all internally treated as strings, and function as placeholders.
 
Source code - File "plain_var"
    1      Following variables:
    2       -  "Number"
    3       -  "Class"
    4       -  "BoolCondition"
    5       -  "String"
    6       -  "Identifier"
    7       -  "Empty"
    8      are currently not set.
    9      @ set  Number=256
   10      @ set  Class=Customer
   11      @ set  Identifier=some_id
   12      @ eval BoolCondition Number>0
   13      @ set  String= plain string with some blanks and various quotes ("'`)
   14      @ set  Empty=
   15      @ add  Number Number
   16      ------------------ After set and eval:
   17      Following variables are now placeholders:
   18       -  "Number"
   19       -  "Class"
   20       -  "BoolCondition"
   21       -  "String"
   22       -  "Identifier"
   23       -  "Empty"
	       

Output of "/opt/somusar/bin/tefigel plain_var"
    1      Following variables:
    2       -  "Number"
    3       -  "Class"
    4       -  "BoolCondition"
    5       -  "String"
    6       -  "Identifier"
    7       -  "Empty"
    8      are currently not set.
    9      ------------------ After set and eval:
   10      Following variables are now placeholders:
   11       -  "512"
   12       -  "Customer"
   13       -  "1"
   14       -  " plain string with some blanks and various quotes ("'`)"
   15       -  "some_id"
   16       -  ""
	       

Two very important operations that can be applied to Tefigel variables via the current dash are string concatenation, shown in the next example, and contents association stored into so-called associative variables; the latter topic requires a more complex example and is described later in the document.

Code Example 8 - String concatenation via DASH

Usage of string concatenation via DASH to generate a Java set method.
 
Source code - File "string_cat"
    1      @ dash $
    2      @ set MEMBER=Quantity
    3      @ set MEMBERTYPE=int
    4          public void set$MEMBER(MEMBERTYPE a$MEMBER) {
    5              this.MEMBER = a$MEMBER;
    6          }
	       

Output of "/opt/somusar/bin/tefigel string_cat"
    1          public void setQuantity(int aQuantity) {
    2              this.Quantity = aQuantity;
    3          }
	       

String concatenation and contents association allow Tefigel users to group Tefigel variables in aggregates like records, lists, mappings and arrays, which are globally referred to as associative variables.

The dash operator is also variable as the command and comment markers previously discussed, to allow Tefigel to flexibly deal with the variety of syntax rules and tokens of as many computer languages as possible.

3.7 - Name Spaces

Tefigel variables are grouped in nested name spaces, or scopes, which are created and deleted either implicitly when a CALL to a subroutine or function is issued, or explicitly by means of PUSH and POP, as shown in the following example.

Code Example 9 - Name spaces

Three nested variables namespaces.
 
Source code - File "namespaces"
    1      Namespace 1) Variable "eks" currently evaluates to 'X'.
    2      @ set X=
    3      Namespace 1) Variable "eks" now evaluates to 'X'.
    4      @ set X=namespace 1
    5      Namespace 1) Variable "eks" now evaluates to 'X'.
    6      @ push
    7          Namespace 2) Variable "eks" now evaluates to 'X'.
    8      @ set X=namespace 2
    9          Namespace 2) Variable "eks" now evaluates to 'X'.
   10      @ push
   11              Namespace 3) Variable "eks" now evaluates to 'X'.
   12      @ set X=namespace 3
   13              Namespace 3) Variable "eks" now evaluates to 'X'.
   14      @ pop
   15          Namespace 2) Variable "eks" now evaluates to 'X'.
   16      @ set X=namespace 2, second value
   17          Namespace 2) Variable "eks" now evaluates to 'X'.
   18      @ pop
   19      Namespace 1) Variable "eks" now evaluates to 'X'.
   20      @ unset X
   21      Namespace 1) Variable "eks" now evaluates to 'X'.
	       

Output of "/opt/somusar/bin/tefigel namespaces"
    1      Namespace 1) Variable "eks" currently evaluates to 'X'.
    2      Namespace 1) Variable "eks" now evaluates to ''.
    3      Namespace 1) Variable "eks" now evaluates to 'namespace 1'.
    4          Namespace 2) Variable "eks" now evaluates to 'namespace 1'.
    5          Namespace 2) Variable "eks" now evaluates to 'namespace 2'.
    6              Namespace 3) Variable "eks" now evaluates to 'namespace 2'.
    7              Namespace 3) Variable "eks" now evaluates to 'namespace 3'.
    8          Namespace 2) Variable "eks" now evaluates to 'namespace 2'.
    9          Namespace 2) Variable "eks" now evaluates to 'namespace 2, second value'.
   10      Namespace 1) Variable "eks" now evaluates to 'namespace 1'.
   11      Namespace 1) Variable "eks" now evaluates to 'X'.
	       

A global name space is also always available via the instruction GLOBSET, which is useful for example to preserve context across subsequent CALLs to the same subroutine. Name spaces are actually very seldom used explicitly via PUSH and POP; in fact, they are internally used by Tefigel to save/restore context before and after subroutine CALLs.

Chapter 4 - Text File Processing

Tefigel provides all the basic tools usually available in most, if not all, procedural languages to enable the implementation of sequential algorithms and to convert an input flow into an output flow, namely computation of arithmetic and logical - or boolean - expressions, language structures to control the processing flow, and input/output instructions to manage the inbound and outbound data flows.

4.1 - Arithmetic Computation

Tefigel has been designed mainly for generating text files and not for complex, general-purpose software systems. Its set of arithmetic instructions comprises thus very basic operations, such as ADD, SUB, MUL, DIV, TRUNC, NEG, as shown by the next example. All computations are performed in floating point, as for a pocket calculator.

Code Example 10 - Arithmetic computation

Simple arithmetic computations: two divisions on lines 5 and 9, and a subtraction on line 7.
 
Source code - File "arith"
    1      # Sample arithmetic computation
    2      @ set A=3
    3      @ set B=6
    4      @ set C=B
    5      @ div C A
    6      B divided by A yields C
    7      @ sub B 1
    8      @ set C=B
    9      @ div C A
   10      B divided by A yields C
	       

Output of "/opt/somusar/bin/tefigel arith"
    1      6 divided by 3 yields 2
    2      5 divided by 3 yields 1.666666666666667
	       

4.2 - Control Flow and Boolean Computation

Control flow in Tefigel is supported by traditional constructs, such as IF..ELSE..ENDIF and WHILE..ENDWHILE. Additionally, instructions LABEL, JUMP, and JUMPCOND allow conditional and unconditional branching. A simple loop is illustrated by the next example.

Code Example 11 - Simple loop

Loop three times, printing out a message on each loop.
 
Source code - File "loop"
    1      ---- Begin loop
    2      @ loop I=0,2
    3          loop #I
    4      @ endloop
    5      ---- End loop
	       

Output of "/opt/somusar/bin/tefigel loop"
    1      ---- Begin loop
    2          loop #0
    3          loop #1
    4          loop #2
    5      ---- End loop
	       

As for arithmetic computation, the language constructs for boolean computation are very primitive in Tefigel: the set of boolean instructions consists of instructions EVAL, AND, OR and NOT, whereas the set of boolean test operators consists of:

The following example shows a typical application of boolean computation to control flow.

Code Example 12 - Boolean computation and control flow

An example of logical computation is given on lines 6 and 7. Conditional control flow (IF..ELSE..ENDIF) is illustrated on lines 8-10-12 and 14-16-18. An example of unconditional branching (goto) is provided on lines 4 and 19.
 
Source code - File "logical"
    1      @ set A=true
    2      @ set B=false
    3      @ set C=unknown
    4      @ label back
    5      ---- Begin logical expression evaluation
    6      @ eval expr A#B
    7      @ and expr A#C
    8      @ if expr=1
    9         A, B, C are all different
   10      @ else 
   11         A, B, C are not all different
   12      @ endif
   13      ---- End logical expression evaluation
   14      @ if C=true
   15      @    quit
   16      @ else
   17      @    set C=true
   18      @ endif
   19      @ jump back
	       

Output of "/opt/somusar/bin/tefigel logical"
    1      ---- Begin logical expression evaluation
    2         true, false, unknown are all different
    3      ---- End logical expression evaluation
    4      ---- Begin logical expression evaluation
    5         true, false, true are not all different
    6      ---- End logical expression evaluation
	       

4.3 - Input and Output

Another main function of Tefigel is constituted by its set of input and output control instructions. Input flow is managed by means of instructions PROCESS and CALL, which respectively allow to process an input file in the same or in a new name space, or by means of instruction ATTACH which barely attaches the contents of a given file to Tefigel's output without actually processing it - that is, without applying neither variable substitution nor instruction recognition.

Output flow is managed by means of instructions OUTPUT and APPEND, which redirect the standard output of Tefigel to a given file, respectively creating it from scratch, or extending it by appending new text to the text that it previously contained.

Code Example 13 - Input and output

Create two output files "outp1" and "outp2" on lines 2 and 7, and extend "outp1" on line 12. Contents are provided by three input files "inp1", "inp2" and "inp3", each of which gets in turn PROCESSed, CALLed and ATTACHed. Note that standard output is left empty, as no output text appears before the first OUTPUT instruction.
 
Source code - File "in_out"
    1      @ set GREETING=Hello!
    2      @ output  outp1
    3      @ process inp1
    4      @ call    inp2
    5      @ attach  inp3
    6      @ set GREETING=Good morning!
    7      @ output  outp2
    8      @ call    inp1
    9      @ attach  inp2
   10      @ process inp3
   11      @ set GREETING=Goodbye!
   12      @ append  outp1
   13      @ attach  inp1
   14      @ process inp2
   15      @ call    inp3
	       

Output of "/opt/somusar/bin/tefigel in_out"
	       

The resulting contents of the output files of this example are listed below.

First output file - File "outp1"
    1      [File "inp1"] Today's greeting is Hello!
    2      [File "inp2"] Today's greeting is Hello!
    3      [File "inp3"] Today's greeting is GREETING
    4      [File "inp1"] Today's greeting is GREETING
    5      [File "inp2"] Today's greeting is Goodbye!
    6      [File "inp3"] Today's greeting is Goodbye!
	       

Second output file - File "outp2"
    1      [File "inp1"] Today's greeting is Good morning!
    2      [File "inp2"] Today's greeting is GREETING
    3      [File "inp3"] Today's greeting is Good morning!
	       

The actual contents of the input files of this example are listed below.

First input file - File "inp1"
    1      [File "inp1"] Today's greeting is GREETING
	       

Second input file - File "inp2"
    1      [File "inp2"] Today's greeting is GREETING
	       

Third input file - File "inp3"
    1      [File "inp3"] Today's greeting is GREETING
	       

Chapter 5 - Modularity

By exploiting the hierarchical nature of the file-systems usually available on most computing platforms, Tefigel strongly encourages a modular approach to the construction of file-generation environments, such as the SoProTech[tm] projects. In particular, subroutines, functions, packages and libraries, all these modular concepts are directly mapped in Tefigel onto standard file-system capabilities, such as files and directories.

5.1 - Subroutines and Functions

One of the key features of Tefigel is its file-oriented implementation of modular programming: Tefigel makes it extremely easy to split the generation of a text file into reusable, modular functions, identified by plain text files that can be directly CALLed by other text files, possibly with parameters, as shown in the following code examples.

Code Example 14 - Generating Java[tm] set/get

Generate a Java code fragment with set and get methods for some class members.
 
Source code - File "java_setget"
    1      
    2      // Set and get methods
    3      @ java/set_get(String,Status,status)
    4      @ java/set_get(ContactInformation,ContactInformation,info)
	       

Output of "/opt/somusar/bin/tefigel java_setget"
    1      
    2      // Set and get methods
    3          public void setStatus(String status) {
    4              this.status = status;
    5          }
    6      
    7          public String getStatus() {
    8              return status;
    9          }
   10      
   11          public void setContactInformation(ContactInformation info) {
   12              this.info = info;
   13          }
   14      
   15          public ContactInformation getContactInformation() {
   16              return info;
   17          }
   18      
	       

Code Example 15 - Subroutine for Java[tm] set/get

Arguments supplied to CALL are made available to subroutines and functions via automatic positional assignments performed by the INTERFACE instruction.
 
Source code - File "java/set_get"
    1      @ interface(MEMBERTYPE,MEMBER,mEMBER)
    2      @ dash $
    3          public void set$MEMBER(MEMBERTYPE mEMBER) {
    4              this.mEMBER = mEMBER;
    5          }
    6      
    7          public MEMBERTYPE get$MEMBER() {
    8              return mEMBER;
    9          }
   10      
   11      @ dash
	       

Beside file-functions, Tefigel provides a set of frequently useful built-in functions, such as LENGTH, SUBSTR, DATE, and several others. These functions are particularly useful in conjunction with the current call key (default: ~), that allows on-the-fly textual substitution of function results, as shown below.

Code Example 16 - Call key and built-ins

Usage of CALLKEY and built-ins within a text file.
 
Source code - File "call_key"
    1      # Embed function calls into output text
    2      This sample shows how to embed call to functions, in particular
    3      built-ins like date, into plain text lines.
    4      String manipulation functions, such as length and substr are
    5      also built in tefigel: 
    6         length of "the quick brown fox" is ~length(the quick brown fox)
    7         substr from position 4 of length 5 of "the quick brown fox" is
    8         "~substr(the quick brown fox,4,5)"
    9      @ callkey $
   10         This script has been run on $date from file $cur_input
   11      @ callkey
   12      # callkey is now again the default ~
	       

Output of "/opt/somusar/bin/tefigel call_key"
    1      This sample shows how to embed call to functions, in particular
    2      built-ins like date, into plain text lines.
    3      String manipulation functions, such as length and substr are
    4      also built in tefigel: 
    5         length of "the quick brown fox" is 19
    6         substr from position 4 of length 5 of "the quick brown fox" is
    7         "quick"
    8         This script has been run on Tue Feb 27 2007 from file call_key
	       

Tefigel's call key is another example of special character, introduced earlier in this tutorial, as it can be dynamically changed to allow for maximum flexibility with respect to the type of input and output of Tefigel itself: a constant call key like, for instance, $ would have caused syntax conflicts when generating source files of languages - such as Unix® shells - that associate a special meaning with the character $.

5.2 - Packages and Libraries

An extensive and modular use of Tefigel rapidly leads to a significant number of Tefigel files, or subroutines, related to one another, that can be collected together as one or more packages. Thanks to its file-oriented approach, Tefigel packages are simply sub-directories within a file-system, that can be freely grouped together at any depth level within the file-system, and then CALLed by means of their pathname.

Aimed at improving code readability, maintainability, and portability, the instruction LIBRARY allows a Tefigel program to search for packages, subroutines and functions under a specified file-system path (the library), thus allowing CALLs to use relative paths instead of absolute ones, as shown below.

Code Example 17 - Library of Tefigel packages

Use a simple list-processing package, consisting of a few subroutines and functions, to show how to use the LIBRARY instruction (on line 18) to dynamically set an entry point to a hierarchical collection of Tefigel packages. Note on lines 14 and 28 that the second parameter to subroutine "list/process" is a list item processor, namely "mkstring".
 
Source code - File "use_list"
    1      @ mark call .
    2      @ mark rem |
    3      @ dash &
    4      --------- Without library: use full pathnames to call tefigel functions
    5      1) Create list.
    6      . lib_root/list/create(EMPLOYEE)
    7      2) Add items to list.
    8      . lib_root/list/add(EMPLOYEE,John Smith)
    9      . lib_root/list/add(EMPLOYEE,Mark Twain)
   10      . lib_root/list/add(EMPLOYEE,Bill Young)
   11      . lib_root/list/add(EMPLOYEE,Tom Rich)
   12      3) List contents: '~lib_root/list/contents(EMPLOYEE)'
   13      4) Process list:
   14      . lib_root/list/process(EMPLOYEE,lib_root/mkstring)
   15      . lib_root/list/delete(EMPLOYEE)
   16      5) List contents after delete: '~lib_root/list/contents(EMPLOYEE)'
   17      --------- With library: use package hierarchy to call tefigel functions
   18      @ library lib_root
   19      1) Create list.
   20      . list/create(EMPLOYEE)
   21      2) Add items to list.
   22      . list/add(EMPLOYEE,John Smith)
   23      . list/add(EMPLOYEE,Mark Twain)
   24      . list/add(EMPLOYEE,Bill Young)
   25      . list/add(EMPLOYEE,Tom Rich)
   26      3) List contents: '~list/contents(EMPLOYEE)'
   27      4) Process list:
   28      . list/process(EMPLOYEE,mkstring)
   29      . list/delete(EMPLOYEE)
   30      5) List contents after delete: '~list/contents(EMPLOYEE)'
	       

Output of "/opt/somusar/bin/tefigel use_list"
    1      --------- Without library: use full pathnames to call tefigel functions
    2      1) Create list.
    3      2) Add items to list.
    4      3) List contents: 'John Smith|Mark Twain|Bill Young|Tom Rich'
    5      4) Process list:
    6         List item 1/4 - first name: "John"; last name: "Smith"
    7         List item 2/4 - first name: "Mark"; last name: "Twain"
    8         List item 3/4 - first name: "Bill"; last name: "Young"
    9         List item 4/4 - first name: "Tom"; last name: "Rich"
   10      5) List contents after delete: ''
   11      --------- With library: use package hierarchy to call tefigel functions
   12      1) Create list.
   13      2) Add items to list.
   14      3) List contents: 'John Smith|Mark Twain|Bill Young|Tom Rich'
   15      4) Process list:
   16         List item 1/4 - first name: "John"; last name: "Smith"
   17         List item 2/4 - first name: "Mark"; last name: "Twain"
   18         List item 3/4 - first name: "Bill"; last name: "Young"
   19         List item 4/4 - first name: "Tom"; last name: "Rich"
   20      5) List contents after delete: ''
	       

Generic list processor - File "lib_root/list/process"
    1      |
    2      |   General-purpose list processing function: scan a list and process
    3      |   each item applying a given item processor
    4      |
    5      @ interface(KEY,PROCESSOR)
    6      |
    7      |   Copy keyed list into CURLIST and keyed count into COUNTER.
    8      |
    9      @ set    CURLIST=~value(KEY&LIST)
   10      @ set CURCOUNTER=~value(KEY&COUNT)
   11      |
   12      |   Quit on empty lists
   13      |
   14      @ if CURCOUNTER<1
   15      @    quit
   16      @ endif
   17      |
   18      |   Loop on list, and call PROCESSOR on each item
   19      |
   20      @ set I=0
   21      @ while I<CURCOUNTER
   22      |
   23      |   Extract i-th field (0-based) from list and pass it to PROCESSOR
   24      |   as (i+1)-th, so that it is 1-based -- easier then to check for
   25      |   last item.
   26      |
   27      @    set ITEM=~field(CURLIST,I,|)
   28      @    add I 1
   29      .    PROCESSOR(I,CURCOUNTER,ITEM)
   30      @ endwhile
	       

Specific list item processor - File "lib_root/mkstring"
    1      |
    2      |   Process I-th item "REC" out of N items by splitting it into
    3      |   two blank-separated fields, "FIRST_NAME" and "LAST_NAME".
    4      |
    5      @ interface(I,N,REC)
    6      @ set FIRST_NAME=~field(REC,0, )
    7      @ set  LAST_NAME=~field(REC,1, )
    8         List item I/N - first name: "FIRST_NAME"; last name: "LAST_NAME"
	       

Therefore the task of creating, extending, and installing a library of Tefigel packages simply consists in creating, adding, and copying text files and directories to a file-system directory that implements the Tefigel library itself.

5.3 - Filters

Filters are Tefigel functions dynamically associated with patterns expressed as regular expressions: when an input line after processing is ready to be written out by Tefigel, a pattern check is performed against the filters currently defined (possibly none), activating the corresponding filter in case of pattern match.

Code Example 18 - Filters

Tefigel FILTERs to print out a specific subset of C preprocessor control lines: the first filter "h_control" captures lines beginning with a #, the second one "h_skip" skips all other lines. Note that the actual input file "errno.h" is specified as a command line parameter to Tefigel.
 
Source code - File "h_filter"
    1      @ mark rem |
    2      @ filter h_control ^#
    3      @ filter h_skip ^.*$
	       

Output of "/opt/somusar/bin/tefigel h_filter errno.h"
    1      #ifndef _ERRNO_H
    2      #ifndef __need_Emath
    3      #include <features.h>
    4      #endif
    5      #include <bits/errno.h>
    6      #ifdef  _ERRNO_H
    7      #ifndef errno
    8      #endif
    9      #ifdef __USE_GNU
   10      #endif /* __USE_GNU */
   11      #endif /* _ERRNO_H */
   12      #endif /* _ERRNO_H */
   13      #if defined __USE_GNU || defined __need_error_t
   14      # ifndef __error_t_defined
   15      # endif
   16      #endif
	       

Code Example 19 - Filter 1

Checks whether the C preprocessor control line should be printed out or not, ignoring #define and #undef. Note on lines 2 and 3 use of comparison operator ~ , pronounced "like".
 
Source code - File "h_control"
    1      @ interface(LINE)
    2      @ eval ignore LINE~^#[  ]*define
    3      @   or ignore LINE~^#[  ]*undef
    4      @ if ignore=0
    5      LINE
    6      @ endif
	       

Code Example 20 - Filter 2

Completely empty script, ignores input and produces no output.
 
Source code - File "h_skip"
	       

Filters are particularly useful in two cases:

Chapter 6 - Multilanguage Applicability

During the design of Tefigel particular care has been taken to keep its syntax as flexible as possible, and allow to use it to generate source files for as many computer languages as possible, at the light of the SoProTech[tm] discussed in "Somusar/Software Production Technique[tm]: An Introduction ". The next chapters contain several short examples where Tefigel is used to produce fragments of source code in different languages belonging to different language classes:

It is worthwile noting that the next simple examples aim at demonstrating the syntactical applicability of Tefigel and its flexibility in the generation of software in the different languages shown below; its practical and industrial applicability are best described in "Somusar/Software Production Technique[tm]: An Introduction ".

The numerous examples of the next paragraphs, as well as the other various code examples scattered across this document, should provide sufficient confidence and insight on the fact that Tefigel can be easily applied as a generic precompiler to practically any computer language, including - beyond the aforelisted languages - several other general-purpose and special-purpose languages and protocols, such as:

The only requirement for a computer language to be generatable by the current version of Tefigel is that its source code can be written in a single-byte character set.

As previously noted, this broad range of applicability was not a merely theoretical target of Tefigel; instead, it was one of the main practical objectives while designing Tefigel as a back-end language for the SoProTech[tm].

Chapter 7 - Generating Object-oriented Languages

7.1 - Java[tm]

Code Example 21 - Generating Java[tm]

Generate set and get methods for two members of a Java class.
 
Source code - File "language/j_getset"
    1      @ dash &
    2      @ language/java/get_set(int,Quantity,quantity)
    3      @ language/java/get_set(double,Percentage,percentage)
	       

Output of "/opt/somusar/bin/tefigel language/j_getset"
    1          public int getQuantity() {
    2              return quantity;
    3          }
    4      
    5          public void setQuantity( int quantity ) {
    6              this.quantity = quantity;
    7          }
    8      
    9          public double getPercentage() {
   10              return percentage;
   11          }
   12      
   13          public void setPercentage( double percentage ) {
   14              this.percentage = percentage;
   15          }
   16      
	       

Java[tm] get/set subroutine - File "language/java/get_set"
    1      @ interface(TYPE,IdId,idId)
    2          public TYPE get&IdId() {
    3              return idId;
    4          }
    5      
    6          public void set&IdId( TYPE idId ) {
    7              this.idId = idId;
    8          }
    9      
	       

7.2 - C#

Code Example 22 - Generating C#

Generate set and get methods for two members of a C# class.
 
Source code - File "language/cs_getset"
    1      @ dash &
    2      @ language/cs/get_set(int,Quantity,quantity)
    3      @ language/cs/get_set(double,Percentage,percentage)
	       

Output of "/opt/somusar/bin/tefigel language/cs_getset"
    1          public int Quantity {
    2              get {
    3                  return quantity;
    4              }
    5              set {
    6                  quantity = value;
    7              }
    8          }
    9      
   10          public double Percentage {
   11              get {
   12                  return percentage;
   13              }
   14              set {
   15                  percentage = value;
   16              }
   17          }
   18      
	       

C# get/set subroutine - File "language/cs/get_set"
    1      @ interface(TYPE,IdId,idId)
    2          public TYPE IdId {
    3              get {
    4                  return idId;
    5              }
    6              set {
    7                  idId = value;
    8              }
    9          }
   10      
	       

7.3 - C++

Code Example 23 - Generating C++

Generate set and get methods for two members of a C++ class.
 
Source code - File "language/cpp_getset"
    1      @ dash &
    2      @ language/cpp/get_set(int,Quantity,quantity)
    3      @ language/cpp/get_set(double,Percentage,percentage)
	       

Output of "/opt/somusar/bin/tefigel language/cpp_getset"
    1          int getQuantity() {
    2              return quantity;
    3          }
    4      
    5          void setQuantity( int quantity ) {
    6              this->quantity = quantity;
    7          }
    8      
    9          double getPercentage() {
   10              return percentage;
   11          }
   12      
   13          void setPercentage( double percentage ) {
   14              this->percentage = percentage;
   15          }
   16      
	       

C++ get/set subroutine - File "language/cpp/get_set"
    1      @ interface(TYPE,IdId,idId)
    2          TYPE get&IdId() {
    3              return idId;
    4          }
    5      
    6          void set&IdId( TYPE idId ) {
    7              this->idId = idId;
    8          }
    9      
	       

Chapter 8 - Generating Internet-oriented Languages and Protocols

8.1 - HTML

Code Example 24 - Generating HTML

Generate a set of homogeneous buttons for an HTML form. Lines 6-9 show an example of variable number of arguments provided to a Tefigel subroutine.
 
Source code - File "language/html/formbuttons"
    1      #
    2      #   HTML document browsing buttons
    3      #
    4        <table cellpadding=0 cellspacing=0>
    5          <tr>
    6      @     language/html/formbutton(First)
    7      @     language/html/formbutton(Prev,Prev.)
    8      @     language/html/formbutton(Next)
    9      @     language/html/formbutton(Last)
   10          </tr>
   11        </table>
	       

Output of "/opt/somusar/bin/tefigel language/html/formbuttons"
    1        <table cellpadding=0 cellspacing=0>
    2          <tr>
    3            <td>
    4              <input type="BUTTON" width=60 name="First" value="First">
    5            </td>
    6            <td>
    7              <input type="BUTTON" width=60 name="Prev" value="Prev.">
    8            </td>
    9            <td>
   10              <input type="BUTTON" width=60 name="Next" value="Next">
   11            </td>
   12            <td>
   13              <input type="BUTTON" width=60 name="Last" value="Last">
   14            </td>
   15          </tr>
   16        </table>
	       

HTML subroutine - File "language/html/formbutton"
    1      #
    2      #   HTML form button
    3      #
    4      @ interface(NAME,label)
    5      @ if label=
    6      @    set label=NAME
    7      @ endif
    8      @ set WIDTH=60
    9            <td>
   10              <input type="BUTTON" width=WIDTH name="NAME" value="label">
   11            </td>
	       

8.2 - XML

Code Example 25 - Generating XML

Produce two sets of XML nested tags, complete with values. Depth depends on the number of input parameters.
 
Source code - File "language/xml.in"
    1      @ dash $
    2      @ language/xml(Tag1=Value1,Tag2=Value2)
    3      
    4      @ linebreak \
    5      @ language/xml(\
    6      TagA=ValueA,\
    7      TagB=ValueB,\
    8      TagC=ValueC,\
    9      TagD=ValueD)
   10      
	       

Output of "/opt/somusar/bin/tefigel language/xml.in"
    1      <Tag1>
    2          Value1
    3          <Tag2>
    4              Value2
    5          </Tag2>
    6      </Tag1>
    7      
    8      <TagA>
    9          ValueA
   10          <TagB>
   11              ValueB
   12              <TagC>
   13                  ValueC
   14                  <TagD>
   15                      ValueD
   16                  </TagD>
   17              </TagC>
   18          </TagB>
   19      </TagA>
   20      
	       

XML subroutine - File "language/xml"
    1      @ set I=0
    2      @ set INDENT=
    3      @ set BLANKS=    
    4      #
    5      #    Scan list of arguments, printing
    6      #    out indented open tag clause and value
    7      #
    8      @ while I<REG_COUNT
    9      @    set  ITEM=REG_$I
   10      @    set TAG$I=~field(ITEM,0,=)
   11      @    set VAL$I=~field(ITEM,1,=)
   12      @    set IND$I=INDENT
   13      INDENT<~value(TAG$I)>
   14      INDENT$BLANKS~value(VAL$I)
   15      @    set INDENT=~value(IND$I)BLANKS
   16      @    add I 1
   17      @ endwhile
   18      #
   19      #    Scan list of arguments backward, printing
   20      #    out indented close tag clause
   21      #
   22      @ while I>0
   23      @    sub I 1
   24      ~value(IND$I)</~value(TAG$I)>
   25      @ endwhile
	       

8.3 - SOAP

Code Example 26 - Generating SOAP

Generate a short SOAP request and response, as per Example 1 of document http://www.w3.org/TR/2000/NOTE-SOAP-20000508
 
Source code - File "language/soap"
    1      ---- Simple SOAP Request ----
    2      @ language/soap_code(GetLastTradePrice,symbol/DIS)
    3      ---- Simple SOAP Response ----
    4      @ language/soap_code(GetLastTradePriceResponse,Price/34.5)
	       

Output of "/opt/somusar/bin/tefigel language/soap"
    1      ---- Simple SOAP Request ----
    2      <SOAP-ENV:Envelope
    3       xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    4       SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    5       <SOAP-ENV:Body>
    6         <m:GetLastTradePrice xmlns:m="Some-URI">
    7           <symbol>DIS</symbol>
    8         </m:GetLastTradePrice>
    9       </SOAP-ENV:Body>
   10      </SOAP-ENV:Envelope>
   11      ---- Simple SOAP Response ----
   12      <SOAP-ENV:Envelope
   13       xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   14       SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   15       <SOAP-ENV:Body>
   16         <m:GetLastTradePriceResponse xmlns:m="Some-URI">
   17           <Price>34.5</Price>
   18         </m:GetLastTradePriceResponse>
   19       </SOAP-ENV:Body>
   20      </SOAP-ENV:Envelope>
	       

SOAP request/response fragment - File "language/soap_code"
    1      #
    2      #   REQUEST_RESPONSE_ID contains id of request or response
    3      #
    4      @ interface(REQUEST_RESPONSE_ID,PARAM_INFO)
    5      #
    6      #   PARAM_INFO contains tag/id of parameter #1 - note "/" used as a separator
    7      #
    8      @ set PARAM_TAG_1=~field(PARAM_INFO,0,/)
    9      @ set  PARAM_ID_1=~field(PARAM_INFO,1,/)
   10      <SOAP-ENV:Envelope
   11       xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   12       SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   13       <SOAP-ENV:Body>
   14         <m:REQUEST_RESPONSE_ID xmlns:m="Some-URI">
   15           <PARAM_TAG_1>PARAM_ID_1</PARAM_TAG_1>
   16         </m:REQUEST_RESPONSE_ID>
   17       </SOAP-ENV:Body>
   18      </SOAP-ENV:Envelope>
	       

8.4 - PHP

Code Example 27 - Generating PHP

Generating a PHP fragment that in turn will generate some HTML.
 
Source code - File "language/php"
    1      @ set TITLEHEADER=<h4>
    2      @ set TITLE=Generated PHP fragment
    3      <?php
    4      // Small fragment of PHP, printing out some HTML
    5      print "TITLEHEADER\n";
    6      print "TITLE\n";
    7      ?>
	       

Output of "/opt/somusar/bin/tefigel language/php"
    1      <?php
    2      // Small fragment of PHP, printing out some HTML
    3      print "<h4>\n";
    4      print "Generated PHP fragment\n";
    5      ?>
	       

Chapter 9 - Generating Procedural Languages

9.1 - C

Code Example 28 - Generating C

Generate set and get "methods" for two "members" of a C "class".
 
Source code - File "language/c_getset"
    1      @ dash &
    2      @ language/c/get_set(int,Quantity,quantity)
    3      @ language/c/get_set(double,Percentage,percentage)
	       

Output of "/opt/somusar/bin/tefigel language/c_getset"
    1      static int quantity;
    2      
    3      int getQuantity() {
    4          return quantity;
    5      }
    6      
    7      void setQuantity( int v_quantity ) {
    8          quantity = v_quantity;
    9      }
   10      
   11      static double percentage;
   12      
   13      double getPercentage() {
   14          return percentage;
   15      }
   16      
   17      void setPercentage( double v_percentage ) {
   18          percentage = v_percentage;
   19      }
   20      
	       

C get/set subroutine - File "language/c/get_set"
    1      @ interface(TYPE,IdId,idId)
    2      static TYPE idId;
    3      
    4      TYPE get&IdId() {
    5          return idId;
    6      }
    7      
    8      void set&IdId( TYPE v_&idId ) {
    9          idId = v_&idId;
   10      }
   11      
	       

9.2 - Visual Basic®

Code Example 29 - Generating Visual Basic®

Visual Basic® fragment containing a comment and a message to be printed out in a message box.
 
Source code - File "language/vbasic"
    1      @ set msg=Hello!
    2      ' Print out a message
    3      MsgBox "The message is: msg"
    4      
	       

Output of "/opt/somusar/bin/tefigel language/vbasic"
    1      ' Print out a message
    2      MsgBox "The message is: Hello!"
    3      
	       

9.3 - COBOL

Code Example 30 - Generating COBOL

Small fragment of PROCEDURE DIVISION that prints out a message.
 
Source code - File "language/cobol"
    1      @ set program_name=PROGRAM 0
    2      @ set hello_message=Hello, world!
    3            ****************************************************************
    4             PROCEDURE DIVISION.
    5             P0.
    6            ** print a message
    7                 DISPLAY 'program_name: hello_message'.
    8      
	       

Output of "/opt/somusar/bin/tefigel language/cobol"
    1