Frequently asked questions

- Why a new programming language?
- Which license does Seed7 use?
- But Java and C# are also free?
- On which operating systems does Seed7 run?
- How do I uncompress the *.tgz file from the release?
- How do I compile the Seed7 interpreter?
- I got errors when compiling Seed7. What should I do?
- Does the interpreter use bytecode?
- How does the analyze phase of the interpreter work?
- Is it possible to compile Seed7 programs?
- What are the reserved words of Seed7?
- Why does Seed7 not use the C statements like C++ and Java?
- Isn't the code unreadable if everybody invents new statements?
- Hasn't Lisp already user defined statements and operators?
- Why does Seed7 use static type checking?
- Is the program development slowed down with static type checking?
- Why does Seed7 not use type inference?
- Are there automatic casts to the right type?
- Can I use something and declare it later?
- Can functions be overloaded?
- Can I overload two functions which just differ by the result type?
- Can functions have variable parameter lists?
- Why is it necessary to initialize all variables?
- Is there a garbage collection?
- Is Seed7 object oriented?
- Is everything inherited from object?
- What is multiple dispatch?
- What container classes do exist?
- Are there primitive types?
- What is the difference between object and primitive types?
- When to use an object type and when a primitive type?
- How does the assignment work?
- Why are there two forms of assignment?
- What types of parameters does Seed7 have?
- Where are the constructors?
- Are there static methods / class methods?
- Are there generics / templates?
- Are there exceptions?
- What does action "XYZ_SOMETHING" mean?
- Why are there dollar signs at some places?
- Why does "seed7_05.s7i" contain a version number?
- Can I use an "abc.s7i" include file to boot to the abc language?

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 templates written in Seed7. User defined abstract datatypes 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 hi interpreter is booted with the language description when it starts. This way it is possible to define language variants or a totally different language.

Which license does Seed7 use?

The hi 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 hi 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.

But Java and C# are also free?

Seed7 is "Free as in Freedom" and not only "Free as in Free Beer" and this can make a big difference. Undocumented native interfaces are just not possible.

On which operating systems does Seed7 run?

Linux is supported out of the box (because the development is done using Linux). I used Seed7 also under various UNIX variants, so it is probably easy to port Seed7 to a UNIX variant. Windows is supported with MinGW, Cygwin (it may be necessary to change some include or library paths), the stand alone compiler of MSVC (cl.exe) and the stand alone compiler of the BDS (bcc32.exe). 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' 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 > s7.tar
      $ tar -xvf s7.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 dependend 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 to C compiler comp.sd7) 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|compiler|shell
      -------------+-----------------+---------+--------+--------
      mk_linux.mak | linux/unix/bsd  | (g)make | gcc    | sh
      mk_cygw.mak  | windows (Cygwin)| (g)make | gcc    | sh
      mk_msys.mak  | windows (MinGW) | (g)make | gcc    | sh
      mk_mingw.mak | windows (MinGW) | (g)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_osx.mak   | Mac OS X (Xcode)| make    | gcc    | sh

In the optimal case you just copy one of this files to 'makefile' and do:

        make depend
        make

If you try different makefiles 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

      scr_inf.c:57:18: error: term.h: No such file or directory
      kbd_inf.c:55: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

        echo char *getcwd(char *buf, size_t size); >> seed7lib.c
        /usr/bin/sh: -c: line 0: syntax error near unexpected token `('

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.

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, compiler, the version of Seed7 you wanted to compile and the complete log of error messages to seed7-users@lists.sourceforge.net .

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 according to the syntax definitions. For each expression the analyzer searches the internal database of declared objects (this search process is called matching) and generates call-code for this expression. Then the call code for this expression is executed. Normally this expressions are declaration statements. In that case new declared objects are added to the internal database.

Is it possible to compile Seed7 programs?

Generally Seed7 is designed to allow the compilation from Seed7 to C. The Seed7 compiler (written in Seed7) 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. (Note that the compiler is currently not finished)

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'`, `'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 behaviour 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.

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:

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;

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 in 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 an 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 and might issue warnings at compile time (this is implementation dependent). 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. Additionally it would be necessary to repeat all this 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 initialisation, 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. 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.

Why does Seed7 not use type inference?

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

      For every expression (and sub expression) you know its type at
      compile time without knowing 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?

No, because Seed7 is strong typed. This means that for every expression (and sub expression) you know its type at compile time without knowing where this expression is used. Although this means that you have to convert types explicit (for example from integer to float) it has more advantages than disadvantages:

1. The overloading rules are much simpler.
2. An expression can be understood without it's 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 by the result type?

No, it is not possible to overload a function (operator, statement) which has the same parameter types and just a different result type as another function. This is necessary to reach the goal of knowing the type of every expression without knowing where the expression is used.

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));

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 there a garbage collection?

There is no garbage collection process that interrupts the normal processing to free some memory. Seed7 uses a different mechanism to manage the memory.

Memory used by local variables and parameters is automatically freed when leaving a function.

Although functions can return arbitrary complex values (e.g. arrays of structures with string elements) the memory allocated for all intermediate results is freed automatically without the help of a garbage collector. This is done in a stack like manner. The same way as arithmetic expressions like (1+2)*3+4 can be evaluated with the help of a stack (which stores the intermediate results 3 and 9), it is possible to maintain a stack of pointers to arbitrary complex values. Note that the point where such intermediate results should be freed can be determined 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 at compile time.

Is Seed7 object oriented?

Yes, but object orientation is organized different compared to other object oriented languages.

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 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 param) + (in Number param) 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: val is 0;
        end struct;

      type_implements_interface(Integer, Number);

      const type: Float is new struct
          var float: val 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: result is Float.value;
        begin
          result.val := flt(a.val) + b.val;
        end func;

      const func Float: (in Float: a) + (in Integer: b) is func
        result
          var Float: result is Float.value;
        begin
          result.val := a.val + flt(b.val);
        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: result is Integer.value;
        begin
          result.val := a.val + b.val;
        end func;

      const func Float: (in Float: a) + (in Float: b) is func
        result
          var Float: result is Float.value;
        begin
          result.val := a.val + b.val;
        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'`, `'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.

What types of parameters does Seed7 have?

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

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

Additionally every type defines an `'in'` parameter which is either a `'val'` or a `'ref'` parameter. Types with little memory requirements like `'integer'`, `'char'` or `'boolean'` use a `'val'` parameter as `'in'`. Other types like `'string'`, arrays and structs use a `'ref'` parameter as `'in'`. Usually it is not necessary to care if an `'in'` parameter is by value or by reference.

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: result is 0;
        begin
          result := 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 a 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. A Seed7 program consists of a sequence of declarations, which are executed one by one at compile time. Since declarations are just a form of statement it can be concluded that other statements can as well be used at the top level.

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 the Ada and Java exceptions.

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 .

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 declared. 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 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's, return's and break's 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 hi 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).