

Frequently asked questions
==========================


Why a new programming language?
===============================

Because Seed7 has several features which are not found in other
programming languages:

 - The possibility to declare new statements (syntactical and
   semantically) in the same way as functions are declared (There are
   also user definable operators with priority and associativity).
 - Declaration constructs for constant-, variable-, function-,
   parameter-, and other declarations are described in Seed7 (The user
   can change existing declaration constructs or invent new ones).
 - Templates use no special syntax. They are just functions with
   type parameters or a type result.
 - Seed7 has abstract data types. For example the types array, hash,
   struct and set. They are not hard coded in the compiler, but are
   abstract data types written in Seed7. User defined abstract data
   types are also possible.
 - The object orientation of Seed7 allows multiple dispatch. That
   means that a function or method is connected to more than one type.
 - Seed7 is a syntactically and semantically extensible language:
   Almost all of the Seed7 language (statements, operators,
   declaration constructs, and more) is defined in Seed7 in an include
   file (seed7_05.s7i).
 - The application program contains an include statement and the s7
   interpreter is booted with the language description when it starts.
   This way it is possible to define language variants or a totally
   different language.


What is an extensible programming language?
===========================================

An extensible programming language supports mechanisms to extend the
programming language, compiler/interpreter and runtime environment.
The programmer is allowed to define new language constructs such as
statements, declaration constructs and operators syntactically
and semantically. Most programming languages allow user defined
variables, functions and types, but they also use constructs which
are hard-coded in the compiler/interpreter. An extensible programming
language tries to avoid such hard-coded constructs in normal programs.

Extensible programming was an area of active research in the 1960s,
but in the 1970s the extensibility movement was displaced by the
abstraction movement. Todays software history gives almost no hint
that the extensible languages movement had ever occurred. In the
historical movement an extensible programming language consisted of
a base language providing elementary computing facilities, and a
meta-language capable of modifying the base language. A program then
consisted of meta-language modifications and code in the modified
base language. A popular approach to do language extension was the
use of macro definitions. The constructs of the base language were
hard-coded.

The design and development of Seed7 is based on independent research,
which was done without knowing that the historic extensible
programming language movement existed. Although Seed7 has different
roots it reaches many of the original extensible programming language
goals. Contrary to the historic movement Seed7 does not have a
meta-language. In Seed7 a language extension is formulated in Seed7
itself. Seed7 differentiates between syntactic and semantic extensions.
Syntactic extensions are described in Chapter 9 (Structured syntax
definition) of the manual. The semantic extensions of Seed7 are done
by declaring statements and operators as functions. For the body of
loops and similar needs statically typed call-by-name parameters are
used.


Are Seed7 programs portable?
============================

Yes. Seed7 spares no effort to support source code portability.
No changes are necessary, when programs are moved between different
processors, between 32- and 64-bit systems or between little- and
big-endian machines. Seed7 source code can also be moved between
different operating systems. Several driver libraries assure that
the access to operating system resources such as files, directories,
network, clock, keyboard, console and graphics is done in a portable
way. The libraries of Seed7 cover many areas. The goal is: There
should be no need to call foreign C functions, or to execute shell
(respectively cmd.exe) commands.

 - Seed7 determines the properties of the underlying C compiler and
   C runtime library and uses code to compensate the differences.
 - Different Unicode encodings (e.g.: UTF-8 or UTF-16) in system
   calls (e.g. fopen()/wopen()) are hidden from the programmer.
 - Portable file functions are provided in the library osfiles.s7i:
    - There are functions to copy, move and remove files (and
      directory trees).
    - File properties such as size, type, time and mode can be
      obtained and changed.
    - The contents of a directory can be read as array of strings or
      via the file interface.
    - A standard path representation removes all problems with
      drive letters and different path delimiters.
 - Differences between Unix sockets and winsockets are hidden and
   a Seed7 socket is a file (as in Unix). The type pollData allows
   to wait until a socket is ready to read or write data. TLS/SSL
   and higher level protocols such as HTTP, HTTPS, FTP
   and SMTP are also supported.
 - The library keybd.s7i defines the file KEYBOARD, which supports
   reading single key presses. The characters read from KEYBOARD are
   not echoed to the console and there is no need to press ENTER.
   There is also a portable way to check, if a key has been pressed.
 - Reading keys and key combinations such as ctrl-F1 from a text
   console or a graphic window under different operating systems
   always delivers the same character code.
 - There is an access to the text console, which allows cursor
   positioning.
 - An operating system independent type for times and dates, based
   on the proleptic Gregorian calendar, is provided in the library
   time.s7i.
 - A portable graphics library allows drawing, image operations,
   windows manipulation and bitmap fonts. Events to redraw a window
   and other annoyances are managed in the graphics library.
 - A database access library provides the possibility to connect to
   MySql/MariaDb, SQLLite, PostgreSQL, Oracle and Odbc databases.
 - Weaknesses of operating systems are hidden (E.g.: The windows
   function utime() does not work on directories, but Seed7 allows
   the modification of directory access and modification times also
   under windows).


Which license does Seed7 use?
=============================

Seed7 is "Free as in Freedom" and not only "Free as in Free Beer".
The s7 interpreter and the example programs (extension .sd7) are under the
GPL (General Public License, see also the file COPYING).

The Seed7 runtime library is under the LGPL (Lesser General Public License,
see also the file LGPL). The Seed7 include files (extension .s7i) are a part
of the Seed7 runtime library.

Seed7 allows the interpretation and compilation of programs with any license.
There is no restriction on the license of your Seed7 programs.

For the development of the Seed7 compiler it will be necessary to move some
source code from the s7 interpreter (under GPL) to the Seed7 runtime library
(under LGPL). This will only be done to for the Seed7 runtime library and only
as far as necessary to make no restriction on the license of compiled Seed7
programs.

If you send me patches (I would be very pleased), it is assumed that you
accept license changes from GPL to LGPL for parts of code which need to be
in the runtime library to support compilation of Seed7 programs.


Is Seed7 a descendant of Pascal?
================================

No, not really. The keywords and statements remind people of Pascal,
but behind the surface there is much difference. Don't judge a book
by its cover. Seed7 is neither limited to Pascal's features, nor is it
implemented like Pascal. Notable differences are:

  Feature            | Standard Pascal             | Seed7
  -------------------+-----------------------------+-----------------------------
  syntax             | hard-coded in the compiler  | defined in a library
  statements         | hard-coded in the compiler  | defined in a library
  operators          | hard-coded in the compiler  | defined in a library
  array              | hard-coded in the compiler  | defined as abstract data type 'array'
  record / struct    | hard-coded in the compiler  | defined as abstract data type
  hash table         | not in the standard library | defined as abstract data type 'hash'
  compiler target    | machine code or P-code      | C, compiled to machine code afterwards
  template           | none                        | function with type parameters
  abstract data type | none                        | function with type result
  object orientation | none                        | interfaces and multiple dispatch

Except for LL(1) parsing, no technology used by classical Pascal
compilers could be used to implement Seed7.


How does Seed7 compare to Java?
===============================

Several features of Seed7 are missing in Java:

  Features missing in Java                  | Comment
  ------------------------------------------+----------------------------------------------
  Stand alone functions                     | Singletons must be used instead
  Call-by-reference parameters              | All parameters are call-by-value
  Call-by-name parameters                   | All parameters are call-by-value
  Operator overloading                      | No possibility to use + for BigInteger values
  User defined operators                    | -
  User defined statements                   | -
  User defined syntax                       | -
  Elegant way to express data structures    | Property files and XML must be used instead
  User defined functions to initialize data | -
  Multiple dispatch                         | -
  Checking for integer overflow             | -
  Escape sequences only as part of literals | Unicode escapes can be everywhere. That can cause unexpected effects



What kind of programs can be written in Seed7?
==============================================

Seed7 can be used in various application areas:

 - Applications, like an Excel look-alike (Seed7 is a general purpose
   language and programs can be compiled to an executable).
 - Scripts that deal with files and directories (The Seed7 Homepage
   and the Seed7 release are created with Seed7 scripts).
 - Tools for networking (There is support for sockets, TLS/SSL, listeners,
   HTTP, HTTPS, FTP, SMTP and HTML parsing). E.g.:
    - A ftp file transfer program
    - A ftp server
    - A web server
 - Programs that deal with XML (There is support for XML parsing and
   the possibility to read XML into a DOM data structure).
 - CGI scripts (A CGI support library is available and the Comanche
   web server can be used to test CGI scripts).
 - As language to describe algorithms.
 - Command line utilities. E.g.:
    - A calculator that works like a read-eval-print loop (REPL)
    - A make utility capable to process Unix and Windows makefiles
    - A tar archiving utility
    - A program to save a potentially damaged harddisk partition to an image file
 - 2D games. E.g.:
    - Panic
    - Mahjong solitaire
    - Pairs
 - Simulations. E.g.:
    - Planet Wator Predator-Prey simulation
    - Bacteria which fight against each other
 - Functions to explore mathematics. E.g.:
    - Mandelbrot set
    - Bifurcation
    - Cellular automaton


How many lines of code are in the Seed7 project?
================================================

The Seed7 package contains more than 100000 lines of C and more
than 200000 lines of Seed7. For version 2019-03-03 the number of lines is:

  145391  C source files (*.c)
   11058  C header files (*.h)
  157007  Seed7 source files (*.sd7)
  142174  Seed7 library/include files (*.s7i)

C code (*.c and *.h files) can be divided into the following areas:

   0.3%  Interpreter main
  11.6%  Parser
   2.8%  Interpreter core
  24.7%  Primitive action functions
   7.4%  General helper functions
  48.5%  Runtime library
   4.7%  Compiler data library

Details about this files can be found in the file 'seed7/src/read_me.txt'.


On which operating systems does Seed7 run?
==========================================

Seed7 runs on the following operating systems:

 - Linux is supported with the following compilers:
    - gcc (the development is done using gcc under Linux)
    - clang
    - icc
 - Unix (I used Seed7 also under various Unix variants, so it is probably
   easy to port Seed7 to a Unix variant)
 - BSD (there is a FreeBSD port and an OpenBSD port)
 - Windows is supported with the following compilers:
    - MinGW GCC (the binary Windows release of Seed7 uses MinGW)
    - Cygwin GCC (the X11 graphics needs Cygwin/X)
    - MSVC cl.exe (cl.exe is the stand-alone compiler of MSVC)
    - BDS bcc32.exe (bcc32.exe is the stand-alone compiler of the BDS)
 - DOS (uses DJGPP. Sockets, graphics, processes and databases are currently not supported)
 - Mac OS X is supported with the following compilers:
    - gcc
    - clang

For other operating systems it might be necessary to write driver modules for
screen (=text console), graphics, time or other aspects of Seed7. The package
contains various older driver modules which are not up to date, but can be used
as base to write such driver modules. For more detailed information look at the
files 'seed7/read_me.txt' and 'seed7/src/read_me.txt'.


How do I uncompress the *.tgz file from the release?
====================================================

When you have a gnu 'tar' program available you can just do

  $ tar -xvzf seed7_05_yyyymmdd.tgz

If your 'tar' command does not accept the 'z' option
you need to uncompress the file first with 'gunzip':

  $ gunzip seed7_05_yyyymmdd.tgz
  $ tar -xvf seed7_05_yyyymmdd.tar

Sometimes the browser downloads a *.gz file instead of a *.tgz file.
In that case you could also use 'gunzip' as shown above. As
an alternative you can also use 'zcat':

  $ zcat seed7_05_yyyymmdd.gz > seed7.tar
  $ tar -xvf seed7.tar

Under windows you can use the 7-Zip compression/decompression utility
(there is no relationship to Seed7). 7-Zip is open source software and is
available at: www.7-zip.org.


How do I compile the Seed7 interpreter?
=======================================

The way to compile the interpreter is dependent on the operating system and the
development tools used. You need a stand-alone C compiler and a make utility to
compile the interpreter. A C compiler which is only usable from an IDE is not so
useful, since some Seed7 programs (e.g. The Seed7 compiler s7c) need to call the
C compiler as well. To compile the interpreter under Linux just go to the 'src'
directory and type:

  make depend
  make

For other cases several makefiles are prepared for various combinations of
operating system, make utility, C compiler and shell:

  makefile name|operating system |make prog     |C compiler  |shell
  -------------+-----------------+--------------+------------+--------
  mk_linux.mak | Linux/Unix/BSD  | (g)make      | gcc        | sh
  mk_clang.mak | Linux/Unix/BSD  | (g)make      | clang      | sh
  mk_icc.mak   | Linux/Unix/BSD  | (g)make      | icc        | sh
  mk_tcc_l.mak | Linux/Unix/BSD  | (g)make      | tcc        | sh
  mk_cygw.mak  | Windows (Cygwin)| (g)make      | gcc        | sh
  mk_msys.mak  | Windows (MSYS)  | mingw32-make | gcc        | sh
  mk_mingw.mak | Windows (MinGW) | mingw32-make | gcc        | cmd.exe
  mk_nmake.mak | Windows (MinGW) | nmake        | gcc        | cmd.exe
  mk_msvc.mak  | Windows (MSVC)  | nmake        | cl         | cmd.exe
  mk_bcc32.mak | Windows (bcc32) | make         | bcc32      | cmd.exe
  mk_bccv5.mak | Windows (bcc32) | make         | bcc32 V5.5 | cmd.exe
  mk_djgpp.mak | DOS             | (g)make      | gcc        | cmd.exe
  mk_osx.mak   | Mac OS X        | make         | gcc        | sh
  mk_osxcl.mak | Mac OS X        | make         | clang      | sh
  mk_freebsd.mk| FreeBSD         | make         | clang/gcc  | sh

In the optimal case you just copy one of this files to 'makefile' and do (with
the make program from the table above):

  make depend
  make

When the interpreter is compiled successfully the executable and the libraries
are placed in the 'bin' directory. Additionally a symbolic link to the executable
is placed in the 'prg' directory (Under Windows symbolic links are not supported,
so a copy of the executable is placed in the 'prg' directory). The Seed7 compiler
(s7c) is compiled with:

  make s7c

The compiler executable is copied to the 'bin' directory. If you do several
compilation attempts in succession you need to do

  make clean

before you start a new attempt. More details about the compilation process can
be found in the file 'seed7/src/read_me.txt'.


I got errors when compiling Seed7. What should I do?
====================================================

In most cases errors indicate that some development package of your
distribution is missing. If your operating system is Linux, BSD or Unix
not all development packages with header files might be installed. In
this case you get some errors after typing 'make depend'. Errors such as

  chkccomp.c:56:20: fatal error: stdlib.h: No such file or directory
  s7.c:30:20: fatal error: stdlib.h: No such file or directory

indicate that the development package of the C library is
missing. I don't know the name of this package in your
distribution (under Ubuntu it has the name libc6-dev), but
you can search for C development libraries and header files.

Errors such as

  con_inf.c:54:18: error: term.h: No such file or directory
  kbd_inf.c:53:18: error: term.h: No such file or directory
  trm_inf.c:47:18: error: term.h: No such file or directory

indicate that the curses or ncurses development package is missing.
I don't know the name of this package in your distribution
(under Ubuntu it has the name libncurses5-dev), but you
can search in your package manager for a curses/ncurses
package which mentions that it contains the header files.
To execute programs you need also to install the non-developer
package of curses/ncurses (in most cases it will already
be installed because it is needed by other packages).

Errors such as

  drw_x11.c:38:19: error: X11/X.h: No such file or directory
  drw_x11.c:39:22: error: X11/Xlib.h: No such file or directory
  drw_x11.c:40:23: error: X11/Xutil.h: No such file or directory
  drw_x11.c:45:24: error: X11/keysym.h: No such file or directory

indicate that the X11 development package is missing.
Under Ubuntu this package has the name libx11-dev and is
described as: X11 client-side library (development headers)
Note that under X11 'client' means: The program which wants to
draw. A X11 'server' is the place where the drawings are displayed.
So you have to search for a X11 client developer package with
headers. If you use X11 in some way (you don't do everything
from the text console) the non-developer package of X11 will
already be installed.

Errors such as

  gcc chkccomp.c -lm -o chkccomp
  chkccomp.c:28:21: fatal error: version.h: No such file or directory
  compilation terminated.
  mingw32-make: *** [version.h] Error 1

or

  del version.h
  process_begin: CreateProcess(NULL, del version.h, ...) failed.
  make (e=2): The system cannot find the file specified.
  mingw32-make: *** [clean] Error 2

indicate that your makefile contains commands for the cmd.exe
(or command.com) windows console, but your 'make' program uses
a Unix shell ('/usr/bin/sh') to execute them. Either use a
makefile which uses Unix shell commands (e.g. mk_msys.mak or
mk_cygw.mak) or take care that the 'make' program uses cmd.exe
(or command.com) to execute the commands.

Errors such as

  s7.c:28:21: error: version.h: No such file or directory

indicate that you forgot to run 'make depend' before running
'make'. Since such an attempt produces several unneeded files it
is necessary now to run 'make clean', 'make depend' and 'make'.

When you got other errors I would like to know about. Please
send a mail with detailed information (name and version) of
your operating system, distribution, C compiler, the version of
Seed7 you wanted to compile and the complete log of error
messages to seed7-users@lists.sourceforge.net .


How do I verify that the interpreter works correct?
===================================================

A comprehensive test of the s7 interpreter and the s7c
compiler can be done in the directory 'prg' with the command:

  ./s7 chk_all

Under windows using ./ might not work. Just omit the ./ and
type:

  s7 chk_all

The program 'chk_all' uses several check programs to do its
work. First a check program is interpreted and the output
is compared to a reference. Then the program is compiled and
executed and this output is also checked. Finally the C code
generated by the compiled compiler is checked against the C
code generated by the interpreted compiler. The checks of
the compiler are repeated with several compiler options. If
everything works correct the output is (after the usual
information from the interpreter):

  compiling the compiler - okay
  chkint ........... okay
  chkovf ........... okay
  chkflt ........... okay
  chkbin ........... okay
  chkchr ........... okay
  chkstr ........... okay
  chkprc ........... okay
  chkbig ........... okay
  chkbool ........... okay
  chkset ........... okay
  chkhsh ........... okay
  chkexc ........... okay

This verifies that interpreter and compiler work correct.


How can I install Seed7?
========================

After Seed7 interpreter and compiler have been compiled and
verified they can be installed. The makefiles support the
target install. You need appropriate privileges to do the
installation. Depending on the operating system there are
different strategies to get the privileges:

 1. Unix-like operating systems

    Just go to the directory 'seed7/src' and type:

      sudo make install

    With the make command of your computer. The sudo command
    will ask you for your password. When your permissions are
    sufficient the command creates symbolic links in the
    directory '/usr/local/bin'.

 2. Windows

    You need to open a console as administrator. Then you can
    go to the directory 'seed7/src' and type:

      make install

    With the make command of your computer. This adds the
    directory 'seed7/bin' to the search path (PATH variable).
    You need to start a new console to see the effect of this
    change.

More details can be found in the file 'seed7/doc/install.txt'.


How can I use the Seed7 interpreter?
====================================

The s7 interpreter is called with the command

  s7 [options] sourcefile [parameters]

Note that the 'options' must be written before the 'sourcefile'.
If the 'sourcefile' is not found .sd7 is appended to the 'sourcefile'
and searched for that file.

The following options are recognized by s7:

  -?   Write Seed7 interpreter usage.
  -a   Analyze only and suppress the execution phase.
  -dx  Set compile time trace level to x. Where x is a string consisting
       of the following characters:
         a Trace primitive actions
         c Do action check
         d Trace dynamic calls
         e Trace exceptions and handlers
         h Trace heap size (in combination with 'a')
         s Trace signals
  -d   Equivalent to -da
  -i   Show the identifier table after the analyzing phase.
  -l   Add a directory to the include library search path (e.g.: -l ../lib).
  -p   Specify a protocol file, for trace output (e.g.: -p prot.txt).
  -q   Compile quiet. Line and file information and compilation
       statistics are suppressed.
  -s   Deactivate signal handlers.
  -tx  Set runtime trace level to x. Where x is a string consisting
       of the following characters:
         a Trace primitive actions
         c Do action check
         d Trace dynamic calls
         e Trace exceptions and handlers
         h Trace heap size (in combination with 'a')
         s Trace signals
  -t   Equivalent to -ta
  -vn  Set verbosity level of analyse phase to n. Where n is one
       of the following characters:
         0 Compile quiet (equivalent to -q)
         1 Write just the header with version information (default)
         2 Write a list of include libraries
         3 Write line numbers, while analyzing
  -v   Equivalent to -v2
  -x   Execute even when the program contains errors.

  In the program the 'parameters' can be accessed via 'argv(PROGRAM)'.
  The function 'argv(PROGRAM)' delivers an array of strings. The number
  of parameters is 'length(argv(PROGRAM))' and 'argv(PROGRAM)[1]'
  returns the first parameter.


Is it possible to compile Seed7 programs?
=========================================

Generally Seed7 is designed to allow the compilation from Seed7 to C. The Seed7
compiler (s7c) is written in Seed7. It uses the analyze phase of the interpreter
to convert a program to call-code and then generates a corresponding C program.
This C program is compiled and linked afterwards. The Seed7 compiler can be
called with:

  s7c [ options ] source

Possible options are

  -?   Write Seed7 compiler usage.
  -O and -O2  Tell the C compiler to optimize.
  -b   Specify the directory of the Seed7 runtime libraries (e.g.: -b ../bin).
  -e   Generate code which sends a signal, when an uncaught exception occurs.
       This option allows debuggers to handle uncaught Seed7 exceptions.
  -g   Tell the C compiler to generate an executable with debug information.
       This way the debugger will refer to Seed7 source files and line numbers.
       To generate debug information which refers to the temporary C program
       the option -g-debug_c can be used.
  -l   Add a directory to the include library search path (e.g.: -l ../lib).
  -ocn Optimize constants with level n. E.g.: -oc3
       The level n is a digit between 0 and 3:
         0 Do no optimizations with constants.
         1 Use literals and named constants to simplify expressions (default).
         2 Evaluate constant parameter expressions to simplify expressions.
         3 Like -oc2 and additionally evaluate all constant expressions.
  -p   Activate simple function profiling.
  -sx  Supress checks specified with x. E.g.: -sr or -sro
       The checks x are specified with letters from the following list:
         r Suppress the generation of range checks for strings and arrays.
         o Suppress the generation of integer overflow checks.
  -tx  Set runtime trace level to x. Where x is a string consisting
       of the following characters:
         e Trace exceptions and handlers
         f Trace functions
         s Trace signals


Can I debug Seed7 programs with Eclipse?
========================================

Yes, Eclipse can be easily configured to work with Seed7:

  Eclipse needs the C/C++ Development Tools (CDT) plugin.
  In Window => Preferences => C/C++ => FileTypes add *.sd7 as 'C Source File'
       and *.s7i as 'C Header File'.
  In Window => Preferences => General => Editors => File Associations add *.sd7
       and *.s7i and make the C/C++ Editor default for them.
  Create a C project (New => Project => C/C++ => C Project).
  Right click on the project in the Project Explorer and select Properties => C/C++ General => File Types.
       Check if the workspace settings are used. If not add *.sd7 as 'C Source File'
       and *.s7i as 'C Header File'.
  In a console window: Compile your Seed7 program with the option -g.
  In Eclipse: Create a Debug Configuration with: Run => Debug Configurations...
       Right click on C/C++ Application and select New.
  In the Main tab of the new Debug Configuration: Press the Browse... button
       to select the executable you want to debug.
  Select the C project you created.
  In the Arguments tab you can set program arguments and current working directory.
  Press the Debug button to start the program.


What are the reserved words of Seed7?
=====================================

In Seed7 there are no reserved words. Instead there are keywords which are
used at various places. Some keywords introduce statements or other constructs
(such as declarations). E.g.: The keywords 'if', 'while', 'repeat', 'for',
and some others introduce statements. Other keywords like 'do', 'then', 'range',
'result', etc. are used in the middle of statements (or other constructs).
Finally there are also keywords like 'div', 'rem', 'lpad', 'times', etc. which
are used as operator symbols.

Seed7 uses syntax declarations to specify the syntax of statements. A keyword
is a name which is used somewhere in a syntax declaration. Syntax declarations
reduce the possibilities to use a keyword out of context. E.g.: After the keyword
'if' the parser expects always an expression. This makes 'if' unusable as
variable name. This way you get error messages when you try to use 'if' or
other keywords as variable name. That behavior is just the same as in other
languages which have reserved words. It can be summarized that Seed7 reaches
the goal of avoiding the misuse of keywords in other ways and not by reserving
them altogether.

In a classic compiler (e.g. a Pascal compiler) there is a distinction between
reserved words and identifiers. Pascal compilers and probably also Ada, C/C++,
Java and C# compilers use an enumeration type to represent the reserved words.
Since Seed7 allows user defined statements (which may introduce new keywords)
it is not possible to hard code reserved words in the compiler as it is done in
Pascal, Ada, C/C++, Java and many other compilers.


How is the syntax of Seed7 defined?
===================================

The syntax of Seed7 is described with the Seed7 Structured Syntax Description
(S7SSD). The S7SSD is similar to an Extended Backus-Naur Form (EBNF), but there are
important differences. S7SSD does not distinguish between different nonterminal
symbols. Instead it only knows one nonterminal symbol: () . S7SSD syntax rules do
not define named nonterminal symbols (EBNF rules define named nonterminal symbols).
S7SSD syntax rules are introduced with:

  $ syntax

S7SSD syntax rules define a pattern of terminal and nonterminal symbols separated
by dots. A S7SSD syntax rule defines also a priority and associativity. The syntax
of the + operator is:

  $ syntax expr: .(). + .()   is -> 7;

The syntax of statements and other constructs is defined as if they were also
operators:

  $ syntax expr: .while.().do.().end.while   is -> 25;

S7SSD is a simple syntax description that can be used by humans and compilers
respectively interpreters. The syntax of a Seed7 program is defined in the library
"syntax.s7i". When a Seed7 program is interpreted or compiled the syntax
definitions are read from "syntax.s7i".


Why does Seed7 not use the C statements like C++ and Java?
==========================================================

The C statements have some weaknesses which are avoided with the Seed7 statements:

 1. The C if-statement

      if (condition)
        statement;

    allows just one statement after the condition. By using the compound statement
    it is possible to have several statements after the condition

      if (condition) {
        statement1;
        statement2;
      }

    Adding or removing a statement in the second if-statement is always possible.
    In the first if-statement you must add braces if you add a statement otherwise
    you get an undesired effect. Adding statements to an if-statement is quite
    common.

    Since both forms are legal and adding a statement to the first form can lead to
    errors Seed7 closes this possible source of errors with its if-statement:

      if condition then
        statement
      end if;

 2. The following switch statement is formally correct but probably wrong

      switch (number) {
        case 1:
        case 2:
          result = 5;
        case 3:
        case 4:
          result = 8;
          break;
        default:
          result = 0;
      }

    Forgetting break statements in a switch is another possible source of errors
    which is avoided with the case-statement of Seed7:

      case number of
        when {1, 2}:
          result = 5;
        when {3, 4}:
          result = 8;
        otherwise:
          result = 0;
      end case;


Isn't the code unreadable if everybody invents new statements?
==============================================================

There are lots of possibilities to write unreadable code without using the
extension features of Seed7. The programmer is (as always) responsible to write
readable programs. The variable/type/function names and other things chosen by
the programmer can always lead to obfuscated code.

Defining new statements and operators is a feature which should not be used in
every program by every programmer. It is a feature which allows experienced
programmers, to write libraries which use statement or operator syntax instead
of function syntax, in areas where such a notation is already accepted practice.

Statements to access a database or operators for vector arithmetic would be such
an example. Another example is a construct which can be used in the definition of
text adventure games.

The possibility to define statements allows also a more precise language
definition. The C++ for/while/if statements are described in the C++ manuals
using BNF and an English description. Seed7 statements can be defined in Seed7.
For example:

  $ syntax expr: .while.().do.().end.while is -> 25;

  const proc: while (ref func boolean: condition) do
                (ref proc: statement)
              end while is func
    begin
      if condition then
        statement;
        while condition do
          statement;
        end while;
      end if;
    end func;

The syntax and semantic of a while-statement is described using an if-statement
and recursion. For performance reasons the implementation will usually use a
different approach to implement a while-loop, but this example shows the expressive
power of Seed7.


Hasn't Lisp already user defined statements and operators?
==========================================================

Defining the semantic of a new 'statement' in Lisp is a classic example.
Normally such 'statements' still use the list notation with lots of parentheses.
The read macros of Lisp could be used to define the syntax of a statement, but
read macros make no type checks at compile time. Any type checking must be written
by the programmer and is not mandated by Lisp. The type checks will be performed
at runtime. Depending on the implementation there might be warnings issued at
compile time. In general: Lisp 'statement' declarations do not force compile time
checks and look less elegant. Seed7 statement declarations force a type check at
compile time.

While Lisp allows new and overloaded functions, the Lisp 'operators' are
functions which use the prefix notation (with lots of parentheses).
Again read macros could be used to support infix operators with priority
and associativity. This read macros would have the same problems as above.
Although Lisp fanatics would never admit it, infix operators with priority
and associativity are not really supported by Lisp. If somebody tells you
that everything can be done in Lisp, send him to the next advocacy group.
In general: Seed7 supports user definable infix operators with priority and
associativity. Such operators can be overloaded and the type checks are done
at compile time. In Lisp all this would be a hack.


Why does Seed7 use static type checking?
========================================

With static type checking all type checks are performed during compile time.
Type errors, such as an attempt to divide an integer by a string, can be
caught earlier (unless this unusual operation has been defined). The key point
is that type errors are found without the need to execute the program. Some
type errors can be hidden in rarely executed code paths. Static type checking
can find such errors easily. With dynamic type checking extensive tests are
necessary to find all type errors. Even tests with 100% code coverage are not
enough since the combination of all places where values are created and all
places where these values are used must be taken into account. That means that
testing cannot guarantee to find all type errors that a static type checker
can find. Additionally it would be necessary to repeat all tests every time
the program is changed. Naturally there are doubts that enough tests are done
and that the tests are adjusted and repeated for every change in the program.
Therefore it can be said that compile time type checks increase the reliability
of the program.

Seed7 makes sure that the object values always have the type of the object.
This goal is reached with mechanisms like mandatory initialization, runtime
checks and the impossibility to change arbitrary places in memory. When the
generation of garbage values is avoided, it can be guaranteed that only legal
values of the correct type are used as object values. This way runtime type
checks are unnecessary and the program execution can be more efficient.

Type declarations can also serve as a form of documentation, because they can
illustrate the intent of the programmer. Although static type checking is very
helpful in finding type errors, it cannot replace a careful program design.
Some operations, allowed by the static type system, can still be wrong because
of different measurement units or other reasons. In the end there are also
other possible sources of errors, such as range violations.

Interface types can be used when an object can have several types at runtime.
In this case the interface type of the object can be determined at compile time
and the type of the object value (implementation type) can vary at runtime.
The static type checking can still check the interface type and the presence
of interface functions. Additionally the compiler can also check that all
functions granted by the interface type are defined for the implementation type.


Is the program development slowed down with static type checking?
=================================================================

No, especially when the time spent to debug a program is taken into account.
Except for artificial corner cases all type errors found by a "nitpicking"
compiler correspond to runtime type errors that can happen in a dynamically
typed language under some circumstances. That way the compile time type checks
save the time necessary to find and debug those errors. The time that a compiler
needs to find and flag type errors is so small that it can be ignored in this
comparison.

Some people claim, that adding type information to a program is a time consuming
process. This is only true when the type information is added afterwards, but
it is wrong when type considerations take place during the program development.
Every good programmer has some concepts about what values will be hold by
variables or parameters and what values will be returned by functions. A good
type system helps to formalize the type concepts which are already in the mind of
the programmer. That way the ideas of the programmer are also documented.

When comparing compile time and runtime type checking it can be concluded that
dynamic typed languages save some programming time by omitting type
declarations, but this time must be paid back with massive interest rates to do
the debugging.


How can static type checking work when types are first-class objects?
=====================================================================

This question refers to something which seems paradox: When Seed7 types are
created at runtime how can they be checked at compile time. The simple answer
is that a type created at runtime cannot be used to define something in
the program that is currently running.

Seed7 declarations are not executed at runtime. Functions with type parameters
and type result are executed at compile time. This is done in templates and
abstract data types (both are executed at compile time). It is possible to have
type variables and type expressions at runtime but is not possible to declare
objects with such a variable type for the program which currently runs. Such
type variables and type expressions are used in the Seed7 compiler.


Why does Seed7 not use type inference?
======================================

Seed7 has a basic principle that would break if type inference would be used:

   The type of every expression (and sub expression) is known at compile time.
   This is independent from the place where this expression is used.

It is exactly the violation of this principle that makes type inference possible.
As long as this principle holds you need to know the global and local declarations
to find out the result type of an expression. With type inference it is necessary
to take other expressions in the local function and even expressions in other
functions into account. I do not say that this is not possible (for sure it is an
interesting challenge to invent an algorithm to do this). But the reader of the
program needs to use this algorithm also every time he/she reads the program. And
that is very bad since a program is more often read than written.


Are there automatic casts to the right type?
============================================

Seed7 cannot read the mind of the programmer. It is hard to find out what the
programmer considers as "right type". A conversion can lose information. Apart
from truncating integers also seemingly safe conversions may lose information.
E.g. Not all 64-bit integer values can be represented as 64-bit float values.
It can also lead to unplanned behavior, when the programmer is not aware of an
automatic conversion. It improves readability when conversions are done explicit.
Seed7 is strong typed and uses explicit conversions. E.g.: The conversion from
'integer' to 'float' is done with the function 'flt'. Conversions from 'float'
to 'integer' are done with 'round' or 'trunc'. Explicit conversions have more
advantages than disadvantages:

 1. The overloading rules are much simpler.
 2. An expression can be understood without its calling context.
 3. Errors caused by unplanned automatic type conversions cannot happen.
 4. Since you have to do type conversions explicit you are more aware of the
    run time overhead.


Can I use something and declare it later?
=========================================

No, everything must be declared before it is used. The possibility to declare new
statements and new operators on one side and the static typing requirements with
compile time checks of the parameters on the other side would make the job of
analyzing expressions with undeclared functions very complex.

Forward declarations help, if something needs to be used before it can be declared
fully.


Can functions be overloaded?
============================

Yes, functions, operators and statements can be overloaded. Additionally it is
possible to define new operators and statements.


Can I overload two functions which just differ in the result type?
==================================================================

No, it is not possible to overload functions (operators, statements) which have
the same parameter types and just differ in the result type. This type of
overloading has a big advantage:

   The type of every expression (and sub expression) is known at compile time.
   This is independent from the place where this expression is used.

Therefore it is not possible to overload something which has no parameters (like
a variable or a literal). As a consequence it is sometimes necessary to cast a
literal to get an unambiguous expression. This concept parallels the approach
used in mathematics where it is also required to specify measurement units.
Obviously there is a difference between 5 seconds, 5 square meters and 5 apples.
In school it is usually considered wrong to just write 5 and let the teacher
guess the measurement unit.


Can functions have variable parameter lists?
============================================

No, because functions with variable parameter list as the C printf function have
some problems:

 - Normally type checking is only possible at run time.
 - The recognition of overloaded functions becomes more complicated.

Instead Seed7 has array aggregates and allows functions with arrays as parameters.
So you could declare a function

  const proc: print_list (in array integer: arr) is func
    local
      var integer: number is 0;
    begin
      for number range arr do
        writeln(number);
      end for;
    end func;

and call it with

  print_list([](1, 1, 2, 3, 5, 8, 13, 21, 34, 55));


Is there an elegant way to initialize data?
===========================================

Most languages allow that a constant is initialized with a constant expression.
This usually rules out user defined functions (or it is restricted in other ways).
Seed7 allows arbitrary expressions (including user defined functions) in
initializations of constants and variables:

  const integer: limit is 1000 ** 2 * 10;

  var string: s7Page is getHttp("seed7.sourceforge.net");

  const func array string: getWords (in string: fileName) is
      return split(lower(getf(fileName)), "\n");

  var array string: dict is getWords("unixdict.txt");

  const set of integer: primes is eratosthenes(limit);

  const PRIMITIVE_WINDOW: pic is readBmp("head3.bmp");

  const array integer: someData is [](1, 1, 2, 3, 5, 8, 13, 21, 34, 55);

A nice example is the initialisation of the table stars with
the function genStarDescr in the library stars.s7i.


Why is it necessary to initialize all variables?
================================================

Forgetting to initialize a variable is a common source of errors. In some
programming languages uninitialized variables have a random value which could lead
to errors. To avoid errors caused by uninitialized variables in Seed7 each variable
must be initialized when it is declared.


Is Unicode supported?
=====================

Seed7 characters and strings support Unicode.
Unicode values are encoded with UTF-32. All functions which exchange
strings with the operating system automatically convert the strings
from and to UTF-32. It is possible to read and write files with Latin-1,
UTF-8 and UTF-16 encoding. Functions to deal with code pages and functions
to convert between different Unicode encodings are also available.

The usage of UTF-32 has several advantages. With UTF-32 it is not
necessary to distinguish character-length from byte-length. The
character-length of an UTF-8 or UTF-16 string must be computed by
processing the whole string. The character-length of an UTF-32
string does not need such an effort. Accessing a character with an
index in an UTF-32 string is also simple. With UTF-8 and UTF-16 it
is necessary to process all characters up to the index. UTF-32 uses
more memory, but todays computers are equipped with a lot of memory.
The pressure to save memory is gone and the easy and fast handling
of UTF-32 strings outweights the increased memory usage.

Conversions to upper and to lower case use the default Unicode case mapping,
where each character is considered in isolation. Characters without case
mapping are left unchanged. The mapping is independent from the locale.
Individual character case mappings cannot be reversed, because some
characters have multiple characters that map to them.

Seed7 source code allows Unicode in char literals, string literals, block comments
and line comments. Interpreter and compiler assume that a Seed7 program is written
with UTF-8 encoding. Therefore a program editor with UTF-8 encoding should be used.

There is also support for Unicode names. The support for Unicode names
is switch off by default and must be activated with the pragma:

  $ names unicode;

This pragma allows variables with e.g. german umlauts or cyrillic letters.
This way beginners can use variable and function names from their native
language.


Are there regular expressions?
==============================

Regular expressions are a powerful feature. Unfortunately they lead also
to code, that is hard to maintain. The regular expression language is
usually embedded in a surrounding programming language. As with other
language in language features this leads to maintenance problems. There
are also other difficulties. Regular expressions work typeless but Seed7
does not. For this reasons regular expressions are currently not supported,
but there is an alternative (see below).

Seed7 has support for lexical scanner functions. Scanner functions use the
LL(1) aproach, which is used in compilers. Practically no compiler uses
regular expressions to parse a program. Scanner functions work strictly
from left to right. They examine one character and do decisions based on
this character. How scanner functions work is described in the manual.
Scanner functions for strings are defined in scanstri.s7i and scanner
functions for files are defined in scanfile.s7i.


Why is the div operator used for integer divisions?
===================================================

In Pascal and Ada the keyword 'div' is used as integer division operator. Other
languages like C and its descendants use / for integer division. Using 'div' has
some advantages:

 - It opens the opportunity to use / for a different purpose. The library
   rational.s7i defines / to create a rational number.
 - An integer division truncates the result. In the common case the result is not
   equal to that of a floating point division (E.g.: flt(4 div 3) returns 1.0,
   but flt(4) / flt(3) returns 1.333333). This difference is emphasized by using
   different operator symbols.
 - A negative result of a division can be rounded towards zero or towards minus
   infinite. Seed7 provides both possibilities with the two integer division
   operators 'div' and 'mdiv'.

The chapter about the type 'integer' in the manual describes properties of integer
divisions and contains tables that show their behavior.


Why are & and <& defined for string concatenation?
==================================================

The operators & and <& both concatenate strings, but they have different purposes.

 - The & operator is intended for string concatenations in normal expressions.
   The & operator does not convert an integer (or some other value) to a string.

   The priority of & is defined to execute the concatenation before doing a
   comparison. E.g.:

     name & extension = check

   has the meaning

     (name & extension) = check

   So the & operator can be used like + - * (the expression is evaluated and its
   result can be compared).

 - The <& operator is intended for write statements. It is overloaded for many
   types. As long as the first or the second parameter is a string it does convert
   the other parameter to a string (with the function str) and does the
   concatenation afterwards.

   The priority of <& is defined to allow also the output of boolean expressions.
   E.g.:

     name <& extension = check

   has the meaning

     name <& (extension = check)

   Note that 'extension' and 'check' could be e.g. integers. The result of
   'extension = check' is converted to string with the function str. So

     writeln(name <& extension = check)

   would write (when 'name' is "asdf" and 'extension' is not equal to 'check'):

     asdfFALSE

The <& operator can be defined for new types with enable_io respectively
enable_output. The description of the Seed7 file system contains also a chapter
about the conversion to strings and back.


What types of parameters does Seed7 have?
=========================================

There are call-by-value and call-by-reference parameters. The formal parameter
can be constant or variable. The combination of these features allows four types
of parameters:

  +-----------+---------------------+--------------+
  | parameter | evaluation strategy | access right |
  +-----------+---------------------+--------------+
  | val       |    call-by-value    | const        |
  | ref       |  call-by-reference  | const        |
  | in var    |    call-by-value    | var          |
  | inout     |  call-by-reference  | var          |
  +-----------+---------------------+--------------+

For call-by-value parameters ('val' and 'in var') the actual parameter value
is copied, when the function is called. For call-by-refererence parameters
('ref' and 'inout') the function uses a reference to the actual parameter value.
Since a call-by-reference parameter is not copied it can provide better
performance for structured types like strings, arrays, structs and hashs.


What is an 'in' parameter?
==========================

An 'in' parameter describes, that the actual parameter value is going into
the function. Inside the function an 'in' parameter cannot be changed.
'In' parameters are the most commonly used evaluation strategy for parameters.

An 'in' parameter is either a 'val' (call-by-value) parameter or a 'ref'
(call-by-reference) parameter. Every type defines an 'in' parameter:

 - For types with little memory requirements 'in' is a val (call-by-value) parameter:
     boolean, integer, float, char, category, reference, enumeration,
     clib_file, pixel, PRIMITIVE_SOCKET

 - For types with bigger memory requirements 'in' is a ref (call-by-reference) parameter:
     bigInteger, rational, bigRational, complex, string, array, hash,
     set, bitset, struct, interface, ref_list, program, color, time,
     duration, file, text, proc, type, object

Usually it is not necessary to care, if an 'in' parameter uses call-by-value or
call-by-reference. A programmer can just use 'in' parameters to specify, that
the actual parameter value is going into the function. A programmer can use
'val' or 'ref' to overrule this behavior in cases, where the default
'in' parameter specified by a type is not desired.


Is there an example where val and ref parameters have different behavior?
=========================================================================

Normally 'val' and 'ref' parameters behave the same. Only in corner cases
their behavior differs. This is shown with the following example:

  $ include "seed7_05.s7i";

  var integer: aGlobal is 1;

  const proc: aFunc (val integer: valParam, ref integer: refParam) is func
    begin
      writeln(valParam <& " " <& refParam);
      aGlobal := 2;
      writeln(valParam <& " " <& refParam);
    end func;

  const proc: main is func
    begin
      aFunc(aGlobal, aGlobal);
    end func;

The program above writes:

  1 1
  1 2

The different behavior is triggered when 2 is assigned to the global variable
aGlobal:

 - The 'val' parameter (valParam) is unaffected by the change of aGlobal,
   because the actual parameter value was copied when the function was called.
 - The 'ref' parameter (refParam) changes when aGlobal is changed.

The effect happens for any type, not just for 'integer' parameters. The same
effect happens also, when an additional 'inout' parameter is used instead of
a global variable and when the function is called with the same variable as
actual parameter for all three parameters.

When a programmer has to deal with such corner cases it is necessary
to explicitly use 'val' or 'ref'.


What is call-by-name?
=====================

Call-by-name is an evaluation strategy for parameters. The actual call-by-name
parameter is not evaluated before the function is called. When the function is
executed the call-by-name parameter might be executed once, many times or not at
all. Examples of call-by-name parameters are:

 - The conditions of while-loops
 - The statements in loop bodies
 - The statements that are conditionally executed in
   an if-statement
 - The right operand of the boolean operators 'and' and 'or'

As can be seen, call-by-name parameters are used all the time, without realizing
it. A call-by-name parameter is a function without parameters. Function types such
as 'proc' or 'func boolean' are used as type of formal call-by-name parameters.
An expression with the correct type is allowed as actual call-by-name parameter. This
actual parameter expression is not evaluated when the function is called. Instead
the call-by-name expression is evaluated every time the formal call-by-name
parameter is used. A 'conditional' function (similar to the ?: operator from C)
is defined with:

  const func integer: conditional (in boolean: condition,
      ref func integer: trueValue, ref func integer: falseValue) is func
    result
      var integer: conditionalResult is 0;
    begin
      if condition then
        conditionalResult := trueValue;
      else
        conditionalResult := falseValue;
      end if;
    end func;

Seed7 does not require a special notation (like brackets) for actual call-by-name
parameters, therefore the 'conditional' function can be called with:

  conditional(a >= 0, sqrt(a), a ** 2)

Depending on the condition 'a >= 0' only one of the expressions 'sqrt(a)' and
'a ** 2' is evaluated. This evaluation takes place when 'trueValue' or 'falseValue'
is assigned to 'result'.


What is an integer overflow?
============================

An integer overflow occurs when a calculation produces a result that
cannot be stored in an integer variable. Very popular languages such as
C, C++, Java, Objective-C and Go do not care about integer overflow.
Programs in this languages continue to execute with a wrong value
instead of the correct result. This wrong value can then trigger
dangerous things. A program can make wrong decisions or produce wrong
output, without any hint that an integer overflow occurred. In Seed7
the exception OVERFLOW_ERROR is raised when an overflow occurs.
When performance is important the overflow checking can be switched
off with the compiler option -so.


Is there a garbage collection?
==============================

There is automatic memory management, but there is no garbage collection
process, that interrupts normal processing. There is no situation, where a
garbage collection needs to "stop the world". The automatic memory management
of Seed7 uses different mechanisms. Memory usage can be categorized and for
every category a specific strategy of automatic memory management is used:

 - Memory used by local variables and parameters is automatically freed, when
   a function is left. The interpreter maintains a list of local values and
   frees them. The compiler inserts code, to free the memory used by local
   variables, in front of each return statement.
 - Memory allocated for intermediate results is freed automatically in a stack
   like manner. Like an arithmetic expressions such as (1+2)*3+4 can be
   evaluated with the help of a stack (which stores the intermediate results
   3 and 9). For structured values it is possible to maintain a stack of
   pointers to the values. The interpreter uses a temp flag, which is present
   in every interpreter object, to free memory. The compiler determines the
   point, where intermediate results can be be freed, at compile time.
   Functions, such as the assignment, can abstain from freeing the
   intermediate result and just assign it to the variable. This way it is not
   always necessary to copy arbitrary complex values. All this things can be
   decided by the compiler.
 - Strings, arrays, hashes and other containers manage their memory. E.g.:
   When an element is removed from a hash table the memory used by the element
   is freed as well as the hash table internal data.
 - A struct value can be referred by one struct variable and by several
   interface variables. Struct values use a reference counter to free the
   struct, when no reference to it exists.


Is Seed7 object oriented?
=========================

Yes, but object orientation is organized different compared to other object
oriented languages. In a nutshell: It is based on interfaces and allows multiple
dispatch. Chapter 7 (Object orientation) of the manual contains a detailed
description of the Seed7 object orientation.

An example of an object oriented type is 'file'. A 'file' describes references to
values with some other type. A value of a 'file' can have one of the following
types: null_file, external_file, echo_file, line_file, etc. Each of this 'file'
value types acts differently to the same requests.

For the type 'file' two kinds of functions are defined:

 1. Functions which work for all files the same way.
 2. Dynamic functions which are just an interface. At run time the corresponding
    function defined for the type of the value is used.

Compared to Java the type file can be seen as interface or abstract class, while
the type of the file value can be seen as the class implementing the interface.


Is everything inherited from object?
====================================

There can be several base types, each with their own hierarchy. In many object
oriented languages the class 'object' is used as element of all container classes.
Abstract data types provide a better and type safe solution for containers and
other uses of the root class 'object'. Therefore a single rooted hierarchy is not
needed.


What is the difference between overloading and object orientation?
==================================================================

Overloading is resolved at compile time while object orientation uses dynamic
dispatch which decides at runtime which method should be called. Overloading
resolution uses static types to decide. Dynamic dispatch uses the implementation
type, which is only known at runtime, to decide. Besides this difference
overloading resolution and dynamic dispatch both use the same approach to do the
work: The types and the access rights of all parameters are used in the decision
process.


What is an abstract data type?
==============================

An abstract data type defines, like every other type, a set of functions to handle
data. An abstract data type leaves, like an interface type from OO, the details of
the data representation open. The difference between the two is:

 - An interface type is resolved to an implementation type at runtime.
 - An abstract data type is resolved to a concrete type at compile time,
   when it is used.

Usually an abstract data type uses parameters to resolve to a concrete type.
Examples of abstract data types are arrays, structs and hashes. An abstract 'array'
type needs the element type as parameter. E.g.:

  array string

This 'array' has 'string' elements and uses 'integer' indices.
An abstract 'array', were the index type is also specified as parameters is:

  array [char] string

This 'array' has 'string' elements and uses 'char' indices.
Arrays are present in many programming languages, but they are usually hard-coded
into the compiler / interpreter. Seed7 does not follow this direction. Instead it
introduces abstract data types as common concept behind arrays, structs, hashes
and other types. Like templates abstract data types are implemented with functions
that are executed at compile time. In contrast to templates abstract data types
return a type as result.


What is multiple dispatch?
==========================

Multiple dispatch means that a function or method is connected to more
than one type. The decision which method is called at runtime is done
based on more than one of its arguments. The classic object orientation
is a special case where a method is connected to one class and the dispatch
decision is done based on the type of the 'self' or 'this' parameter.
The classic object orientation is a single dispatch system.

In a multiple dispatch system the methods cannot be grouped to one class
and it makes no sense to have a 'self' or 'this' parameter.
All parameters are taken into account when the dispatch decision is done.
In the following example the interface type 'Number' uses multiple dispatch:

  const type: Number is sub object interface;

  const func Number: (in Number: a) + (in Number: b) is DYNAMIC;

The 'DYNAMIC' declaration creates an interface function for the '+' operator.
The interface type 'Number' can represent an 'Integer' or a 'Float':

  const type: Integer is new struct
      var integer: data is 0;
    end struct;

  type_implements_interface(Integer, Number);

  const type: Float is new struct
      var float: data is 0.0;
    end struct;

  type_implements_interface(Float, Number);

The declarations of the converting '+' operators are:

  const func Float: (in Integer: a) + (in Float: b) is func
    result
      var Float: sum is Float.value;
    begin
      sum.data := flt(a.data) + b.data;
    end func;

  const func Float: (in Float: a) + (in Integer: b) is func
    result
      var Float: sum is Float.value;
    begin
      sum.data := a.data + flt(b.data);
    end func;

The declarations of the normal '+' operators (which do not convert) are:

  const func Integer: (in Integer: a) + (in Integer: b) is func
    result
      var Integer: sum is Integer.value;
    begin
      sum.data := a.data + b.data;
    end func;

  const func Float: (in Float: a) + (in Float: b) is func
    result
      var Float: sum is Float.value;
    begin
      sum.data := a.data + b.data;
    end func;

The decision which '+' operator should be called at runtime is based on the
implementation type ('Integer' or a 'Float') of both arguments of the '+'.


What container classes do exist?
================================

Abstract data types are used to replace container classes. When using an
abstract data type as container you have to specify the type of the element
in the type declaration. Therefore abstract data types are always type safe.
Typeless container classes with object elements do not exist. The only thing
which comes near to this is the 'ref_list' which is used in the reflection.
A 'ref_list' should not be misused as container class. Predefined abstract
data types are:

 - array
   The type 'array baseType' describes sequences of identical elements of
   a 'baseType'

 - hash
   The type 'hash [keyType] baseType' describes hash tables with elements
   of 'baseType' which can be accessed using an index of 'keyType'

 - set
   The type 'set of baseType' describes a set of elements of a 'baseType'

 - struct
   The type 'struct ... end struct' describes all structured types.

Usage examples of abstract data types are:

  array string
  array [boolean] string
  hash [string] boolean
  hash [string] array array string
  set of char
  set of integer


Are there primitive types?
==========================

As in C++, Java, C# and other hybrid object oriented languages there are
predefined primitive types in Seed7. These are 'integer', 'char', 'boolean',
'string', 'float', 'rational', 'time', 'duration' and others. Additionally to the
predefined primitive types there is also the possibility to declare new primitive
types.


What is the difference between object and primitive types?
==========================================================

Variables with object types contain references to object values. This means
that after

  a := b

the variable 'a' refers to the same object as variable 'b'. Therefore changes
of the object value that 'a' refers to, will effect variable 'b' as well (and
vice versa) because both variables refer to the same object.

For primitive types a different logic is used. Variables with primitive types
contain the value itself. This means that after

  a := b

both variables are still distinct and changing one variable has no effect on
the other.

If 'a' and 'b' are declared to have type 'aType' which contains the integer
field 'property' you can do the following:

  b.property := 1;
  a := b;
  b.property := 2;

Everything boils down to the question: What value does 'a.property' have now.

 - When 'aType' is an object type a.property has the value 2 because 'a' and 'b'
   both refer to the same object.
 - When 'aType' is a primitive type a.property has still the value 1 because 'a'
   and 'b' are distinct objects.


When to use an object type and when a primitive type?
=====================================================

You should declare a new primitive type if you don't need the object oriented
paradigm that a variable (and a constant) is just a reference to the object.
Another indication is: If you don't need two concepts of what is equal
(An == operator and an equal method).


How does the assignment work?
=============================

For object types just the reference to the object value is copied. For primitive
types the value itself is copied. Since values can be very big (think of arrays of
structs with string elements) value copies can be time consuming.

In pure object oriented languages the effect of independent objects after the
assignment is reached in a different way: Every change to an object creates a new
object and therefore the time consuming copy takes place with every change. Because
usually changes to an object are more frequent than assignments this approach can
be even more time consuming than the approach using value copies for the
assignment.


Why are there two forms of assignment?
======================================

Seed7 has an approach for the assignment where practical arguments count more than
the classic object oriented principles. In Seed7 every type has its own logic for
the assignment where sometimes a value copy and sometimes a reference copy is the
right thing to do. Exactly speaking there are many forms of assignment since every
type can define its own assignment. If a value copy works like a deep or a shallow
copy can also be defined depending on the type.

For example: For 'integer', 'char' and 'string' variables a value copy is what most
people expect. For files you don't expect the whole file to be copied with an
assignment, therefore a reference copy seems appropriate.

And by the way:
Although it is always stated that in object oriented languages everything is done
with methods, this is just not true. Besides statements and operators in C++ and
Java which are special even Smalltalk treats the assignment and the comparison
special. Seed7 does not have such special treatment for the assignment and the
comparison operators.


Where are the constructors?
===========================

Seed7 does not need constructors, but you can define normal functions which create
a new value in a similar way as constructors do it.

Seed7 uses a special create statement ( ::= ) to initialize objects. Explicit calls
of the create statement are not needed.

The lifetime of an object goes like this:

1. Memory is reserved for the new object (stack or heap memory make no difference
   here).

2. The content of the new memory is undefined (It may contain garbage), therefore a
   create statement is necessary instead of an assignment.

3. The create statements copies the right expression to the left expression taking
   into account that the left expression is undefined.

4. If the object is variable other values can be assigned using the assign
   statement ( := ). The assignment can assume that the left expression contains a
   legal value. This allows that for strings (and some other types which are just
   references to a memory area) the memory containing the old string value (and not
   the memory of the object itself) can be freed when necessary.

5. At the end of the lifetime of an object the destroy statement is executed.
   For strings (and some other types which are just references to a memory area)
   the memory containing the string value (and not the memory of the object itself)
   is freed.

6. The memory of the object is freed.

The first three steps are usually hidden in the declaration statement.


Are there static methods / class methods?
=========================================

Seed7 allows defining functions (procedures and statements) without corresponding
class. When this is not desired Seed7 uses a special parameter, the 'attr'
(attribute) parameter, to archive the functionality of static methods (elsewhere
named class methods) in a more general way. How a static method is declared is
shown in the following example:

  const func integer: convert_to (attr integer, in char: ch) is func
    result
      var integer: converted is 0;
    begin
      converted := ord(ch);
    end func;

The function 'convert_to' can be called as

  number := convert_to(integer, 'a');

Since the result of a function is not used to determine an overloaded function,
this is sometimes the only way to use the same function name for different purposes
as in:

  ch   := convert_to(char,    1);
  stri := convert_to(string,  1);
  ok   := convert_to(boolean, 1);
  num  := convert_to(typeof(num), 1);

Attribute parameters allow a function to be attached to a certain type. But this
concept is much more flexible than static methods (or class methods). A function
can also have several 'attr' parameters and 'attr' parameters can be at any
parameter position (not just the first parameter). Furthermore the type can be the
result of a function as for example typeof(num).


Are there generics / templates?
===============================

The generics (templates) of Ada, C++ and Java use special syntax. In Seed7 you get
this functionality for free without special syntax or other magic.

Generally all Seed7 functions can be executed at compile time or at runtime. The
time of the function execution depends on the place of the call. Declarations are
just a form of statement and statements are a form of expression. A Seed7 program
consists of a sequence of declarations (expressions), which are executed one by one
at compile time. This expressions can also invoke user defined functions.

A function body can contain declaration statements. When such a function is
executed at compile time, it defines things that are part of the program. It is an
error to execute such a function at runtime.

Seed7 uses the word template to describe a function which is executed at compile
time and declares some things while executing (at compile time). Naturally a
template function can have parameters. Especially types as parameters are useful
with template functions. That way a template function can declare objects with the
type value of a parameter.

It is necessary to call template functions explicit. They are not invoked implicit
as the C++ template functions. The explicit calls of template functions make it
obvious what it is going on. This way the program is easier to read.


Are there exceptions?
=====================

Yes, Seed7 has exceptions which are similar to Ada exceptions. Chapter 14.2
(Exceptions) of the manual contains a detailed description of the Seed7 exceptions.


What happens when an exception is not caught?
=============================================

When an EXCEPTION is not caught the program is terminated and the s7 interpreter
writes a stack trace:

  *** Uncaught EXCEPTION NUMERIC_ERROR raised with
  {integer: <SYMBOLOBJECT> *NULL_ENTITY_OBJECT* div fuel_max }

  Stack:
  in (val integer: dividend) div (val integer: divisor) at integer.s7i(95)
  in init_display at lander.sd7(840)
  in setup at lander.sd7(909)
  in main at lander.sd7(1541)

This stack trace shows that a 'div' operation causes a NUMERIC_ERROR (probably a
division by zero) in line 840 of the file "lander.sd7". A short examination in
"lander.sd7" shows that an assignment to 'fuel_max' was commented out to show how
stack traces work.

  A compiled program creates a much shorter crash message:

  *** Uncaught EXCEPTION NUMERIC_ERROR raised at tmp_lander.c(764)

In this case the mentioned file name and line number refers to the temporary
C file or the Seed7 runtime library. To get useful information there are two
possibilities:

 1. Start the program in the interpreter instead.
 2. Compile the program with the options -g -e and start it from a debugger.

When s7c is called with the option -g it instructs the C compiler to generate
debugging information. This way a debugger like gdb can run the program and provide
information. The option -e tells the compiler to generate code which sends a
signal, when an uncaught exception occurs. This option allows debuggers to handle
uncaught Seed7 exceptions. Note that -e sends the signal SIGFPE. This is done even
when the exception is not related to floating point operations.

Chapter 14.4 (Stack trace) of the manual contains a detailed description how to
debug compiled Seed7 programs.


Where does the interpreter look for include libraries?
======================================================

Include libraries with absolute path (an absolute path starts with a forward slash)
are only searched at the specified place. All other include libraries are searched
in several directories. This is done according to a list of library directories
(a library search path). The directories of the list are checked one after another
for the requested include file. As soon as the include file is found the search is
stopped and the file is included. The following directories are in the list of
library directories:

 1. The directory of the interpreted program. E.g.: When the program
    '/home/abc/test/pairs.sd7' is interpreted the directory '/home/abc/test'
    is in the list of library directories.
 2. The directories that are specified at the command-line with the option -l.
 3. The directory containing the predefined Seed7 include libraries. This
    directory is hard-coded in the interpreter (an absolute path like
    '/directory_where_Seed7_was_installed/seed7/lib'). The hard-coded library
    directory is determined when the interpreter is compiled. When the interpreter
    was not compiled from source (binary release) the path '../lib' relative to the
    current working directory is used.
 4. The directory specified with the SEED7_LIBRARY environment variable.
 5. Directories specified in the source file with the library pragma.
    E.g.: The line: $ library "/home/abc/seed7/lib" adds the directory
    '/home/abc/seed7/lib' to the list of library directories.

Seed7 interpreter and compiler (s7c) use the same list of library
directories (the same library search path). When Seed7 is compiled from
source code both (interpreter and compiler) will find the Seed7 include
files automatically. Interpreter and compiler from the binary release will
only find library include files when the path '../lib' relative to the 's7'
or 's7c' executable leads to the library directory. Additionally it is
possible to set the environment variable SEED7_LIBRARY to the absolute path
'/directory_where_Seed7_was_installed/seed7/lib'.


How is the directory of the predefined include libraries determined?
====================================================================

The directory of the predefined include libraries is hard-coded in the interpreter.
This information is determined when the Seed7 interpreter is compiled. The command
'make depend' writes a line, which defines the C preprocessor variable
SEED7_LIBRARY, to the file 'seed7/src/version.h'. E.g.: The file 'version.h'
contains the line:

  #define SEED7_LIBRARY "/home/abc/seed7/lib"

The preprocessor macro SEED7_LIBRARY is used by the function init_lib_path(), which
is defined in 'seed7/src/infile.c'.

Interpreter and compiler use the same strategy to determine the directory with
predefined include libraries.


How does the Seed7 compiler get information about C compiler and runtime?
=========================================================================

The Seed7 compiler needs detailed information about the C compiler and its runtime
library. This information is created when the Seed7 interpreter is compiled. The
command 'make depend' writes C preprocessor macros to 'seed7/src/version.h'. E.g.:

  #define SEED7_LIB "seed7_05.a"
  #define CONSOLE_LIB "s7_con.a"
  #define DRAW_LIB "s7_draw.a"
  #define COMP_DATA_LIB "s7_data.a"
  #define COMPILER_LIB "s7_comp.a"
  #define S7_LIB_DIR "/home/abc/seed7/bin"

The command 'make depend' compiles and executes the program "chkccomp.c", which
also writes preprocessor macros to "version.h". E.g.:

  #define RSHIFT_DOES_SIGN_EXTEND
  #define TWOS_COMPLEMENT_INTTYPE
  #define LITTLE_ENDIAN_INTTYPE

The preprocessor macros used by 'version.h' are described in
'seed7/src/read_me.txt'. The Seed7 library cc_conf.s7i can be used to access
values from "version.h". This library defines ccConf, which is a constant
of type 'ccConfigType'. The type 'ccConfigType' contains elements for various
configuration values. In our example the element S7_LIB_DIR has the value
"/home/abc/seed7/bin". For macros which are either defined or undefined the
configuration value is TRUE respectively FALSE. In our example the element
TWOS_COMPLEMENT_INTTYPE has the value TRUE.

The Seed7 compiler uses the runtime libraries SEED7_LIB, CONSOLE_LIB, DRAW_LIB,
COMP_DATA_LIB and COMPILER_LIB in the directory S7_LIB_DIR when it links object
files to an executable. Config values like RSHIFT_DOES_SIGN_EXTEND,
TWOS_COMPLEMENT_INTTYPE and LITTLE_ENDIAN_INTTYPE are used to control the kind
of C code produced by the Seed7 compiler. The library cc_conf.s7i provides
also access to config values that do not come from "version.h", but are
defined in 'seed7/src/config.h'. E.g.:

  #define WITH_STRI_CAPACITY
  #define ALLOW_STRITYPE_SLICES

This configuration values describe data structures and implementation strategies
used by the Seed7 runtime library. They do not depend on the C compiler and its
runtime library, but they may change between releases of Seed7.


What should a binary Seed7 package install?
===========================================

A binary Seed7 package needs to install four groups of files:

 - The executables of the interpreter (s7 from 'seed7/bin') and the compiler
   (s7c from 'seed7/bin' or 'seed7/prg').
 - The Seed7 include libraries (files from 'seed7/lib' with the extension .s7i).
 - The static Seed7 object libraries (the files 'seed7_05.a', 's7_con.a', 's7_draw.a',
   's7_data.a' and 's7_comp.a' from 'seed7/bin').
 - Documentation files (the files COPYING and LGPL and all files from 'seed7/doc').

The table below shows the suggested directories for Linux/Unix/BSD:

  +---------------------+---------------+-------------------------+
  | Directory           | Macro         | Group of files          |
  +---------------------+---------------+-------------------------+
  | /usr/bin            | -             | Executables (s7 + s7c)  |
  | /usr/lib/seed7/lib  | SEED7_LIBRARY | Seed7 include libraries |
  | /usr/lib/seed7/bin  | S7_LIB_DIR    | Static libraries        |
  +---------------------+---------------+-------------------------+

The macros must be defined, when the interpreter is compiled. This can be done
by calling 'make depend' with:

  make S7_LIB_DIR=/usr/lib/seed7/bin SEED7_LIBRARY=/usr/lib/seed7/lib depend

Afterwards the interpreter can be compiled with 'make' and the Seed7 compiler
can be compiled with 'make s7c'. This three make commands can be combined to

  make S7_LIB_DIR=/usr/lib/seed7/bin SEED7_LIBRARY=/usr/lib/seed7/lib depend s7 s7c

Alternatively the Seed7 compiler can be compiled as post-install step.
This requires that 'seed7/prg/s7c.sd7' is also installed. The actual
compilation of s7c is done with:

  s7 s7c -O2 s7c

It is also possible to compile the Seed7 compiler in the build directory.
In this case it is necessary to specify the directories SEED7_LIBRARY
and S7_LIB_DIR with the options -l and -b:

  ./s7 -l ../lib s7c -l ../lib -b ../bin -O2 s7c

Compiling s7c with a make command should be preferred.


What is necessary to compile Seed7 with database connections?
=============================================================

The Seed7 runtime library provides the possibility to connect to
MySql/MariaDb, SQLLite, PostgreSQL, Oracle and Odbc databases. During
the compilation of the Seed7 interpreter the program "chkccomp.c"
searches for the availability of database connectors. It searches for
database include files and for database libraries. Some database
configuration settings (MYSQL_LIBS, SQLITE3_LIBS, POSTGRESQL_LIBS, ODBC_LIBS)
come from the makefile. For Oracle it is assumed that the environment
variable ORACLE_HOME has been set. Only when database include files and
libraries are found the corresponding database connection part of Seed7
(sql_my.c, sql_ite.c, sql_post.c, sql_oci.c or sql_odbc.c) is added to
the Seed7 runtime library. For a Seed7 package this means, that the
packages for database connection must be installed during the compilation
of the Seed7 interpreter.

Depending on the configuration the database library is linked statically
or dynamically. When a dynamic database library cannot be found at runtime
the function openDatabase returns database.value.


Does the interpreter use bytecode?
==================================

No, the analyze phase of the Seed7 interpreter produces call-code which consists
of values and function calls. This call-code is just handled in memory and
never written to a file. After the analyze phase the call-code is interpreted.


How does the analyze phase of the interpreter work?
===================================================

The analyzer reads successive expressions. The expressions are read with a
table-driven LL(1) recursive descent parser. The parser is controlled by Seed7
syntax definitions. The parser calls a scanner, which skips whitespace and reads
identifiers and literals. Each parsed expression is searched in the internal
database of defined objects. This search process is called matching. The matching
resolves overloaded functions and generates call-code for the parsed expression.
Call-code uses a data structure which is similar to S-Expressions. The analyzer
executes the call-code of the parsed and matched expressions. Normally parsed and
matched expressions represents declaration statements. Executing a declaration
statement adds new defined objects to the internal database.


How does the compiler implement call-by-name parameters?
========================================================

Every function with call-by-name parameters is searched for recursive calls.
When no recursive call of the function is present it can be implemented with
code inlining. In this case every call of the function is inlined and the actual
call-by-name parameters replace all occurrences of the formal call-by-name
parameter in the function body.

When a function cannot be implemented with code inlining (recursive calls occur)
pointers to a closure structure are used as formal call-by-name parameters. This
closure structure contains a function pointer and a structure which represents
the environment of the closure. When a formal call-by-name parameter is used the
function of the closure structure is called with a pointer to the closure
environment as parameter.

When a function with call-by-name parameters is called the following things are
done: For every actual call-by-name parameter a closure structure with the
function pointer and the closure environment structure is generated. An actual
function representing the closure code is also generated. Before a function with a
call-by-name parameter is called a closure structure variable is initialized. This
includes initializing the function pointer and the environment data of the closure
structure variable. Finally a pointer to the closure structure variable is used as
actual call-by-name parameter.


What does action "XYZ_SOMETHING" mean?
======================================

Actions are used to call a corresponding C function in the interpreter.
For example:

The action "INT_ADD" corresponds to the function 'int_add' in the file
'seed7/src/intlib.c'.

Chapter 13 (Primitive actions) of the manual contains a detailed description
of the primitive actions. In the interpreter all action functions get the
parameters as list. The action functions take the parameters they need from the
list, perform the action and deliver a result.


Why are there dollar signs at some places?
==========================================

The $ is used to force the analyzer to use a hard coded expression recognition
instead of the configurable one. This mechanism is used to boot the Seed7 language:

At the beginning of the seed7_05.s7i file nothing is declared. This means that
no statements, no functions, no operators, no types and no variables are predefined.
To boot the Seed7 language the file syntax.s7i is included. The file syntax.s7i
contains only $ commands. First the type 'type' is defined. Declarations of other
types, system variables and syntax descriptions of operators and statements follow.
After finishing the inclusion of syntax.s7i the file seed7_05.s7i contains some $
declarations until the 'const' declaration statement is established. From that point
onward almost no $ statements are needed.


Why does "seed7_05.s7i" contain a version number?
=================================================

The number 05 is actually a 'branch info'. As if C had headers like

  <stdlib_c78.h> /* For K&R C programs */
  <stdlib_c89.h> /* For ANSI C */
  <stdlib_c99.h> /* For C99 */

and your program must include one of these three headers as first include file
(Other include files have no version/branch info in the name). That way nobody is
forced to upgrade an old program (to get no warnings or to make it compile). You
can leave your old K&R program from 1980 as is. When you decide to rewrite your
K&R program to use prototypes, you change the <stdlib...> include file as well.

Programming languages change over long time periods. This results in different
language standards. Seed7 tries to address this problem from the beginning. Since
most of the Seed7's constructs (statements, operators, types, ... ) are defined in
seed7_05.s7i this is the right place to do it.


Can I use an "abc.s7i" include file to boot to the abc language?
================================================================

Theoretically yes. In practice there would be several problems. For example:

 - All primitive actions are defined such that they fit to Seed7.
 - Some concepts like 'goto', 'return' and 'break' are not supported.
 - Some things like comments and $ pragmas are hard coded.

But basically booting various languages was one of the goals of the extensible
programming language Seed7 and the s7 interpreter.

In practice it turned out to be a better approach to steal concepts from other
programming languages and to integrate them in Seed7 than to split the development
in different branches.

The capability to boot a language can be used to allow slightly different
future versions of Seed7 to coexist with the current version. This is also the
reason why the file seed7_05.s7i contains a version number (05).

