Somusar/Tefigel[tm]

A Tutorial Introduction

Francesco Aliverti-Piuri

Copyright © 2003-2012 Somusar

      
      
      
      
      
      
      
      
      
      
      
      
      
      

Copyright © 2003-2012 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 Thu Sep 27 2012 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            ****************************************************************
    2             PROCEDURE DIVISION.
    3             P0.
    4            ** print a message
    5                 DISPLAY 'PROGRAM 0: Hello, world!'.
    6      
	       

9.4 - RPG

Code Example 31 - Generating RPG

RPG fragment containing a comment and a message to be printed out.
 
Source code - File "language/RPG"
    1      @ set msg=Unknown Code
    2       * Display an error message
    3      Dtext               m                       msgtext('msg')
	       

Output of "/opt/somusar/bin/tefigel language/RPG"
    1       * Display an error message
    2      Dtext               m                       msgtext('Unknown Code')
	       

Chapter 10 - Generating Scripting or Special-purpose Languages

10.1 - SQL

Code Example 32 - Generating SQL

SQL fragment containing a comment and a simple SELECT.
 
Source code - File "language/SQL"
    1      @ set sqltable=EMPLOYEE
    2      @ set search_key=POSITION
    3      @ set search_val=Manager
    4      @ dash $
    5      --
    6      -- By convention, each table contains a column with suffix ID.
    7      --
    8      SELECT sqltable$ID FROM sqltable
    9        WHERE search_key = 'search_val';
	       

Output of "/opt/somusar/bin/tefigel language/SQL"
    1      --
    2      -- By convention, each table contains a column with suffix ID.
    3      --
    4      SELECT EMPLOYEEID FROM EMPLOYEE
    5        WHERE POSITION = 'Manager';
	       

10.2 - Perl

Code Example 33 - Generating Perl

Generate a very simple "Hello, World!" Perl script.
 
Source code - File "language/perl"
    1      @ mark rem |
    2      @ set MESSAGE=Hello, world!
    3      @ set VAR=$msg
    4      # Simple Perl Script
    5      VAR = "MESSAGE\n";
    6      
    7      print VAR;
	       

Output of "/opt/somusar/bin/tefigel language/perl"
    1      # Simple Perl Script
    2      $msg = "Hello, world!\n";
    3      
    4      print $msg;
	       

10.3 - Python

Code Example 34 - Generating Python

Generate a Python fragment, containing a "usage" subroutine.
 
Source code - File "language/python"
    1      @ mark rem |
    2      @ set PROGRAM=some_tool
    3      @ set PARAMETERS=[-o output] [input]
    4      # Usage routine for script PROGRAM
    5      def usage():
    6              print "Usage: PROGRAM PARAMETERS"
    7              exit(1)
	       

Output of "/opt/somusar/bin/tefigel language/python"
    1      # Usage routine for script some_tool
    2      def usage():
    3              print "Usage: some_tool [-o output] [input]"
    4              exit(1)
	       

10.4 - REXX

Code Example 35 - Generating REXX

Generate a simple "Hello" script in REXX.
 
Source code - File "language/rexx"
    1      @ set msg=Hello!
    2      /* Simple REXX script */
    3      say "msg"
    4      exit
	       

Output of "/opt/somusar/bin/tefigel language/rexx"
    1      /* Simple REXX script */
    2      say "Hello!"
    3      exit
	       

10.5 - LaTeX

Code Example 36 - Generating LaTeX

Generate a simple LaTeX example.
 
Source code - File "language/latex"
    1      @ set LANG=LaTeX
    2      This is a simple    LANG  example, % --- LANG comment here
    3         with several whitespaces    and % --- one more comment
    4      comments.
	       

Output of "/opt/somusar/bin/tefigel language/latex"
    1      This is a simple    LaTeX  example, % --- LaTeX comment here
    2         with several whitespaces    and % --- one more comment
    3      comments.
	       

Chapter 11 - Advanced Features and Topics

After the basic elements of Tefigel have been introduced, it is now possible to shortly describe some more advanced and useful features and applications of Tefigel.

11.1 - Tefigel and Sisendel

The main driver to the definition and implementation of Tefigel has been its role as the back-end language within the SoProTech[tm], fully described in "Somusar/Software Production Technique[tm]: An Introduction ". Thus, Tefigel - although fully applicable as a powerful stand-alone tool - should be viewed as a part of a larger picture, as illustrated below.

Figure 1 - Tefigel and Sisendel

Figure 1 - Tefigel and Sisendel

This concept is also illustrated and described in "Somusar/Software Production Technique[tm]: A Sample Project ".

11.2 - Multilevel Contents Association

Multilevel contents association is a simple mechanism that can be used to build reference-to-contents relationships stored into associative variables, as the next example shows. "Multilevel" means that nested contents of an aggregated group of data can be directly referenced to at any level of its nesting.

Code Example 37 - Contents association via DASH

Usage of DASH to accomplish contents association. Note that dynamically changing DASH does not impact contents association. Multilevel association is shown on source lines 7, 8, 16, 17, 28 and 30. Built-in VALUE, used on lines 25, 27, 30 and 33, repeatedly expands its parameter - usually an associative variable - until all placeholders therein contained have been substituted with their current value.
 
Source code - File "associate"
    1      #
    2      # Set type definitions for Java
    3      #
    4      @ dash :
    5      @ set Java:Float=double
    6      @ set Java:Boolean=boolean
    7      @ set Java:String:Short=String
    8      @ set Java:String:Long=String
    9      Type definition for "Float" in Java:: JavaFloat
   10      #
   11      # Set type definitions for SQL
   12      #
   13      @ dash /
   14      @ set SQL/Float=decimal(10,2)
   15      @ set SQL/Boolean=char(1)
   16      @ set SQL/String/Short=varchar(20)
   17      @ set SQL/String/Long=varchar(200)
   18      Type definition for "StringLong" in SQL: SQLStringLong
   19      #
   20      # Access values by means of associative operator dash and built-in value
   21      #
   22      @ dash .
   23      @ set Type=Boolean
   24      @ set Language=Java
   25      Definition of "Type" in Language: ~value(Language.Type)
   26      @ set Language=SQL
   27      Definition of "Type" in Language: ~value(Language.Type)
   28      @ set Type=String.Long
   29      Mapping of Type between Java and SQL:
   30         SQL ~value(SQL.Type) maps to Java ~value(Java.Type)
   31      @ set Type=Float
   32      Mapping of Type between Java and SQL:
   33         SQL ~value(SQL.Type) maps to Java ~value(Java.Type)
	       

Output of "/opt/somusar/bin/tefigel associate"
    1      Type definition for "Float" in Java: double
    2      Type definition for "StringLong" in SQL: varchar(200)
    3      Definition of "Boolean" in Java: boolean
    4      Definition of "Boolean" in SQL: char(1)
    5      Mapping of StringLong between Java and SQL:
    6         SQL varchar(200) maps to Java String
    7      Mapping of Float between Java and SQL:
    8         SQL decimal(10,2) maps to Java double
	       

11.3 - Data Translation Filters

Data translation filters are a means to process input textual data that are structured in various regular forms like lists or tables, for instance comma-separated records, or name-value pairs. With Tefigel filters it is rather simple to convert data from tabular form, such as the following file of bar-separated records to - for example - XML.

Input table - File "data_tab"
    1      Name|Position|Age|Salary
    2      
    3      John Smith|Product manager|34|120,000
    4      Mark Twain|Technical writer|67|250,000
    5      # This is a comment and should be ignored by tefigel filters
    6      Bill Young|Java programmer|4|85,000
    7      # This is a comment and should be ignored by tefigel filters
    8      Tom Rich|Millionaire|49|0
	       

It should be noted that the first line in the input file above contains the description of the records, thus making the file self-described. Additional information in the file header would easily allow to associate a complete metadata description of the table contents, specifying for example the type of the data fields.

Code Example 38 - Table filters

Tefigel FILTERs to translate data from raw tabular form into simple XML: the first filter "t_data" processes lines containing separator "|", the second one "t_skip" skips all other lines (empty and comments). Note use of the special character instruction ARGDELIM, that sets the parameter separator to "/" instead of ",".
 
Source code - File "t_filter"
    1      @ argdelim /
    2      @ filter t_data |
    3      @ filter t_skip ^.*$
	       

Output of "/opt/somusar/bin/tefigel t_filter data_tab"
    1          <!-- next record >
    2              <Name> John Smith </Name>
    3              <Position> Product manager </Position>
    4              <Age> 34 </Age>
    5              <Salary> 120,000 </Salary>
    6          <!-- next record >
    7              <Name> Mark Twain </Name>
    8              <Position> Technical writer </Position>
    9              <Age> 67 </Age>
   10              <Salary> 250,000 </Salary>
   11          <!-- next record >
   12              <Name> Bill Young </Name>
   13              <Position> Java programmer </Position>
   14              <Age> 4 </Age>
   15              <Salary> 85,000 </Salary>
   16          <!-- next record >
   17              <Name> Tom Rich </Name>
   18              <Position> Millionaire </Position>
   19              <Age> 49 </Age>
   20              <Salary> 0 </Salary>
	       

Code Example 39 - Table filter 1

This filter splits matching input record into separate fields, and writes them out as XML fragments. Note use of GLOBSET to store field descriptor tags recognized on first input row into global name space variables called COL_0, COL_1, etc. Also note use of built-in FIELD to extract n-th field from the bar-separated record: note that separator "|" is also a parameter to built-in FIELD.
 
Source code - File "t_data"
    1      @ interface(LINE)
    2      @ eval ignore LINE~^#
    3      @ if ignore=0
    4      @    set VAL_0=~field(LINE/0/|)
    5      @    set VAL_1=~field(LINE/1/|)
    6      @    set VAL_2=~field(LINE/2/|)
    7      @    set VAL_3=~field(LINE/3/|)
    8      @    if COL_0=
    9      @       globset COL_0=VAL_0
   10      @       globset COL_1=VAL_1
   11      @       globset COL_2=VAL_2
   12      @       globset COL_3=VAL_3
   13      @    else
   14          <!-- next record >
   15              <COL_0> VAL_0 </COL_0>
   16              <COL_1> VAL_1 </COL_1>
   17              <COL_2> VAL_2 </COL_2>
   18              <COL_3> VAL_3 </COL_3>
   19      @    endif
   20      @ endif
	       

Code Example 40 - Table filter 2

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

Chapter 12 - A More Extensive Example

In large software development projects it is often necessary to maintain a high level of consistency across different development teams using different programming languages. Although this type of consistency is actually one of the main features of the SoProTech[tm], in some simple cases it is possible to achieve a good level of consistency by using just Tefigel.

The next example shows how to effectively and quickly generate consistent Java[tm] and C declarations by FILTERing a textual list of instructions. An HTML documentation file could just as easily be generated.

12.1 - The Input List: An Instruction Set

The starting point of the example is the list of Tefigel instructions. Purpose of the example is to process this list and generate the corresponding sets of declarations in both Java[tm] and C.

Instruction set of Tefigel - File "instr_set"
    1      # Instructions on variables
    2      GLOBSET
    3      POP
    4      PUSH
    5      SET
    6      UNSET
    7      
    8      # Arithmetic instructions
    9      ADD
   10      DIV
   11      MUL
   12      SUB
   13      TRUNC
   14      NEG
   15      
   16      # Logical instructions
   17      AND
   18      EVAL
   19      NOT
   20      OR
   21      
   22      # Control flow
   23      IF
   24      ELSE
   25      ENDIF
   26      WHILE
   27      ENDWHILE
   28      JUMPCOND
   29      JUMP
   30      LABEL
   31      
   32      # Subroutines and functions
   33      CALL
   34      FILTER
   35      LIBRARY
   36      QUIT
   37      RETVALUE
   38      
   39      # Input/output
   40      APPEND
   41      ATTACH
   42      ECHO
   43      MSG
   44      OUTPUT
   45      PROCESS
   46      PROCESS_IF_READABLE
   47      
   48      # Special characters and operators
   49      ARGDELIM
   50      CALLKEY
   51      DASH
   52      ESCAPE
   53      LINEBREAK
   54      MARK
   55      
   56      # Miscellaneous instructions
   57      DUMP
   58      REM
   59      RESET
   60      SWITCH
   61      SYSTEM
   62      VERSION
	       

12.2 - List Filters

The list filter consists of one main script and two input filters, one for processing lines containing instructions and blank lines, one for processing comment lines.

Code Example 41 - List filters

This Tefigel filter produces two output files, creating them via the instruction OUTPUT on lines 9 and 15. It declares on lines 19 and 20 two filters, one for input comment lines (instr_comment), and one for non-comment lines (instr_code). Then it PROCESSes the instruction set on line 21, and APPENDs one trailing line to each file at the end. The filter does not write anything to its standard output, which is thus empty.
 
Source code - File "instr_filter"
    1      @ mark rem |
    2      @ dash $
    3      @ switch STRICT_CMDMARK=1
    4      |
    5      |   Initialization: naming and creation of output files
    6      |
    7      @    globset j_out=Out/InstrSet.java
    8      @    globset h_out=Out/instr_set.h
    9      @    output j_out
   10      //
   11      //   j_out - generated on ~date at ~time
   12      //
   13      
   14      public class InstrSet {
   15      @    output h_out
   16      /*
   17       *   h_out - generated on ~date at ~time
   18       */
   19      @ filter instr_comment ^#
   20      @ filter instr_code ^[^#]*$
   21      @ process instr_set
   22      @ filter instr_code
   23      @ filter instr_comment
   24      @ append j_out
   25      }
   26      @ append h_out
   27      
	       

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

Code Example 42 - List filter 1

This filter counts the instruction codes (variable instruction_code), skips blank input lines, and prints proper Java and C definitions to the corresponding output files. Note use of built-in TABS on lines 22 and 24.
 
Source code - File "instr_code"
    1      @ interface(input_line)
    2      |
    3      |   Skip blank lines on input.
    4      |
    5      @ eval blank input_line~^[      ]*$
    6      @ if blank=1
    7      @    quit
    8      @ endif
    9      |
   10      |   If instruction_code is not set yet, then we are at the beginning
   11      |   of the input file: set it to 0. Otherwise increment it.
   12      |
   13      @ if instruction_code=
   14      @    globset instruction_code=0
   15      @ else
   16      @    add instruction_code 1
   17      @ endif
   18      |   
   19      |   Append definition to both files. Format lines using built-in tabs
   20      |
   21      @ append j_out
   22          ~tabs(public final int input_line   = instruction_code;,40)
   23      @ append h_out
   24      ~tabs(#define INSTR_$input_line instruction_code,40)
	       

Code Example 43 - List filter 2

Translate input comment to proper format, appending it to both output files.
 
Source code - File "instr_comment"
    1      @ interface(input_line)
    2      @ set comment_length=~length(input_line)
    3      @ sub comment_length 1
    4      @ set comment=~substr(input_line,1,comment_length)
    5      @ append j_out
    6      
    7      //
    8      //comment
    9      //
   10      
   11      @ append h_out
   12      
   13      /*
   14       *  comment
   15       */
   16      
	       

12.3 - Generated Java[tm] and C Code

The resulting Java[tm] and C output files are listed below.

The instruction set in Java[tm] - File "Out/InstrSet.java"
    1      //
    2      //   Out/InstrSet.java - generated on Thu Sep 27 2012 at 13:05:13.410
    3      //
    4      
    5      public class InstrSet {
    6      
    7      //
    8      // Instructions on variables
    9      //
   10      
   11          public final int GLOBSET                = 0;
   12          public final int POP                    = 1;
   13          public final int PUSH                   = 2;
   14          public final int SET                    = 3;
   15          public final int UNSET                  = 4;
   16      
   17      //
   18      // Arithmetic instructions
   19      //
   20      
   21          public final int ADD                    = 5;
   22          public final int DIV                    = 6;
   23          public final int MUL                    = 7;
   24          public final int SUB                    = 8;
   25          public final int TRUNC                  = 9;
   26          public final int NEG                    = 10;
   27      
   28      //
   29      // Logical instructions
   30      //
   31      
   32          public final int AND                    = 11;
   33          public final int EVAL                   = 12;
   34          public final int NOT                    = 13;
   35          public final int OR                     = 14;
   36      
   37      //
   38      // Control flow
   39      //
   40      
   41          public final int IF                     = 15;
   42          public final int ELSE                   = 16;
   43          public final int ENDIF                  = 17;
   44          public final int WHILE                  = 18;
   45          public final int ENDWHILE               = 19;
   46          public final int JUMPCOND               = 20;
   47          public final int JUMP                   = 21;
   48          public final int LABEL                  = 22;
   49      
   50      //
   51      // Subroutines and functions
   52      //
   53      
   54          public final int CALL                   = 23;
   55          public final int FILTER                 = 24;
   56          public final int LIBRARY                = 25;
   57          public final int QUIT                   = 26;
   58          public final int RETVALUE               = 27;
   59      
   60      //
   61      // Input/output
   62      //
   63      
   64          public final int APPEND                 = 28;
   65          public final int ATTACH                 = 29;
   66          public final int ECHO                   = 30;
   67          public final int MSG                    = 31;
   68          public final int OUTPUT                 = 32;
   69          public final int PROCESS                = 33;
   70          public final int PROCESS_IF_READABLE    = 34;
   71      
   72      //
   73      // Special characters and operators
   74      //
   75      
   76          public final int ARGDELIM               = 35;
   77          public final int CALLKEY                = 36;
   78          public final int DASH                   = 37;
   79          public final int ESCAPE                 = 38;
   80          public final int LINEBREAK              = 39;
   81          public final int MARK                   = 40;
   82      
   83      //
   84      // Miscellaneous instructions
   85      //
   86      
   87          public final int DUMP                   = 41;
   88          public final int REM                    = 42;
   89          public final int RESET                  = 43;
   90          public final int SWITCH                 = 44;
   91          public final int SYSTEM                 = 45;
   92          public final int VERSION                = 46;
   93      }
	       

The instruction set in C - File "Out/instr_set.h"
    1      /*
    2       *   Out/instr_set.h - generated on Thu Sep 27 2012 at 13:05:13.410
    3       */
    4      
    5      /*
    6       *   Instructions on variables
    7       */
    8      
    9      #define INSTR_GLOBSET                   0
   10      #define INSTR_POP                       1
   11      #define INSTR_PUSH                      2
   12      #define INSTR_SET                       3
   13      #define INSTR_UNSET                     4
   14      
   15      /*
   16       *   Arithmetic instructions
   17       */
   18      
   19      #define INSTR_ADD                       5
   20      #define INSTR_DIV                       6
   21      #define INSTR_MUL                       7
   22      #define INSTR_SUB                       8
   23      #define INSTR_TRUNC                     9
   24      #define INSTR_NEG                       10
   25      
   26      /*
   27       *   Logical instructions
   28       */
   29      
   30      #define INSTR_AND                       11
   31      #define INSTR_EVAL                      12
   32      #define INSTR_NOT                       13
   33      #define INSTR_OR                        14
   34      
   35      /*
   36       *   Control flow
   37       */
   38      
   39      #define INSTR_IF                        15
   40      #define INSTR_ELSE                      16
   41      #define INSTR_ENDIF                     17
   42      #define INSTR_WHILE                     18
   43      #define INSTR_ENDWHILE                  19
   44      #define INSTR_JUMPCOND                  20
   45      #define INSTR_JUMP                      21
   46      #define INSTR_LABEL                     22
   47      
   48      /*
   49       *   Subroutines and functions
   50       */
   51      
   52      #define INSTR_CALL                      23
   53      #define INSTR_FILTER                    24
   54      #define INSTR_LIBRARY                   25
   55      #define INSTR_QUIT                      26
   56      #define INSTR_RETVALUE                  27
   57      
   58      /*
   59       *   Input/output
   60       */
   61      
   62      #define INSTR_APPEND                    28
   63      #define INSTR_ATTACH                    29
   64      #define INSTR_ECHO                      30
   65      #define INSTR_MSG                       31
   66      #define INSTR_OUTPUT                    32
   67      #define INSTR_PROCESS                   33
   68      #define INSTR_PROCESS_IF_READABLE       34
   69      
   70      /*
   71       *   Special characters and operators
   72       */
   73      
   74      #define INSTR_ARGDELIM                  35
   75      #define INSTR_CALLKEY                   36
   76      #define INSTR_DASH                      37
   77      #define INSTR_ESCAPE                    38
   78      #define INSTR_LINEBREAK                 39
   79      #define INSTR_MARK                      40
   80      
   81      /*
   82       *   Miscellaneous instructions
   83       */
   84      
   85      #define INSTR_DUMP                      41
   86      #define INSTR_REM                       42
   87      #define INSTR_RESET                     43
   88      #define INSTR_SWITCH                    44
   89      #define INSTR_SYSTEM                    45
   90      #define INSTR_VERSION                   46
   91      
	       

Chapter 13 - Further Reading

Additional information on the different aspects of the Somusar/Software Production Technique[tm] can be found in the other volumes of the Somusar/SoProTech[tm] Booklet Series, listed below.

Vol. I - somusar/SoProTech: An Introduction

An introduction to the Somusar/Software Production Technique[tm], a new, fast, and efficient technology to make high-quality multifacet software.

Vol. II - somusar/SoProTech: A Sample Project

Description of a sample project, serving as a proof-of-concept for the Somusar/Software Production Technique[tm], and the Somusar/Sisendel[tm] and Somusar/Tefigel[tm] languages. A few code examples are provided and demonstrate the practical applicability of the technique.

Vol. III - somusar/Sisendel: A Tutorial Introduction

A tutorial introduction to Somusar/Sisendel[tm], describing all features of the simple software entity design language. Several code examples practically demonstrate the conciseness and flexibility of the language.

Vol. V - somusar/Sisendel: Reference Guide

Sisendel reference guide: official definition of syntax and semantics of the Somusar/Sisendel[tm] language.

Vol. VI - somusar/Tefigel: Reference Guide

Tefigel reference guide: official definition of syntax and semantics of the Somusar/Tefigel[tm] language.

Vol. VII - somusar/SoProMach: User's Guide

The Somusar/Software Production Machine[tm] User's Guide. How to install and operate SoProMach.

Vol. VIII - somusar/tjpp: User's Guide

The Somusar/tjpp[tm] User's Guide. How to install and operate the Java[tm] preprocessor.

Vol. IX - Code Generation Somusar Style

Proof-of-concept samples of what you can generate with Somusar/SoProMach[tm].