User:Bautsch/Capsula

From Wikibooks, open books for an open world
Jump to: navigation, search
Some examples for workflows from Capsula to other high-level programming languages, meta codes and runtime environments

Capsula is a simple, absolutely structured, type-safe, imperative, object-oriented and graphical computer programming language for expressing application software. It uses a subset of elements which are known from the Pascal family as well as from C family, especially from their most developed descendants Oberon, Java and C#.

To make it as simple and comprehensible as possible many unnecessary elements of its predecessors have been removed. Therefore, the cyclomatic complexity of Capsula itself and the software programmed with Capsula is very low and this significantly facilitates the verification of software. Nevertheless, its expressiveness is powerful enough to realise projects of any size and complexity.

Capsula supports runtime efficient static data types as well as dynamic data types, which allow powerful data structures. It can be transformed to source code of other programming languages, directly be interpreted in runtime environments or compiled to portable meta code or executable code.

Capsula is in the public domain and it subsumes many good and well-established programming elements, but it does not reinvent the wheel. It is rather a vehicle that is

  • common enough to run safely with parts of different manufacturers
  • smooth enough to safe resources
  • robust enough to allow off-road excursions safely
  • cheap enough to be used for public transport
  • small enough to be mobile
  • easy enough to construct scale models
  • solid enough to provide for easy to maintain endurance
  • inert enough to keep developers on rail track
  • safe enough to achieve short braking distances

The elements of Capsula are rectangular and have two table columns in their definition giving the name and the description of an element:

Element
name
Element
description

The description often fits to a simple rectangle, but it may be sub-structured with smaller rectangles. The description has to be read and will be processed and executed firstly from left to right and secondly from top to bottom.

The element description is given according to the Extended Backus-Naur-Form (EBNF) in this document. Capsula code can easily be saved in and loaded from xml-files.

Basic Concepts[edit]

Identifiers[edit]

Identifier Letter {Letter | Digit}

An identifier must start with a letter and can only contain letters and digits. Identifiers are defined using the Latin‘1 extension of the ASCII character set, which is defined in the standard ISO/IEC 8859-1.

Qualified Identifiers[edit]

Qualified identifiers are used to denote complex data or commands and functions. The dot is used to denote sub elements.

QualifiedIdentifier {Identifier "."} Identifier

Designators[edit]

Designators reference to variables of any data type.

Designator QualifiedIdentifier {("[" IntegerExpression "]") | ("." Identifier)}

The integer expression in square brackets is used to denote the index of an array.

Interfaces[edit]

Interfaces are a major and unique concept for defining the name and the scope of main Capsula elements such as packages, modules, signatures, data types or commands.

Interface Identifier "is" Visibility
Visibility "Private" | "Public"

The visibility is expressed by a modifier which allows adjusting the scope of an element which is described by the interface. A private element is only visible in the unit where it is declared, a public element can be accessed from any other unit within the scope by qualified reference.

Signatures[edit]

Signatures are a major and unique concept of Capsula for defining the interface and the data type of constants and of variables as well as of functions and of formal parameters of functions and commands.

Signature Interface Type

For static data types the default values of any elements are the constants "False", "0", "0.0" or Nil (empty string), and for dynamic dara types the default value is always the constant Nil (null pointer).

List Elements[edit]

ListElements Unit | Constant | Type | Variable | FormalParameter | Command | Function | ActualParameter | Statement | Case

Every Capsula list element has exactly one successor and one predecessor element. The predecessor of the first element and the successor of the last element are Nil. List elements are active by default but any list element can be deactivated by the programmer for code testing.

Furthermore, there is a text comment possible for every Capsula element. A comment is always a character string and the default value of the comment is an empty string.

For reasons of simplicity and better readability the comment sections of all Capsula elements are omitted in the following definitions.

ListElement Comment String
isActive Boolean
Predecessor ListElement
Successor ListElement

Packages[edit]

Usually units will be stored as a whole in separate files or separate database sections, and therefore, these units can be considered as storable and basic Capsula elements (EOF = end of file):

Capsula Unit
EOF
Unit Package | Module
Package "Package" Interface {Unit}

Packages can be defined recursively, but they must not contain themselves. Furthermore, they must contain either only sub packages or only modules. A unit which is belonging to a certain package cannot belong to another package, too.

Modules[edit]

The concept of the module may be interpreted as a unit of compilation.

Module "Module"
Interface
{Constant}
{Type}
{Variable}
{Command}
{Function}
Init
Exit

All constants, types, variables, commands and functions of a module are static. Dynamic programming is fully supported by using dynamic data types such as arrays and classes.

Init "initModule" {Statements}

The statements of the element labelled initModule are executed directly after all imported modules and the module itself are loaded to the run time system. They can be used to initialise the variables of a module and to execute any other statements.

Exit "exitModule" {Statements}

The statements of the element labelled exitModule are executed directly befor the module itself is removed from the run time system. They can be used to finalise the variables of a module and to execute any other statements.

Constants[edit]

Constants cannot be changed during runtime and may only use one basic data type (Boolean, Integer, Real or String).

Constant "Constant" Signature ConstantExpression
ConstantExpression Expression

Types[edit]

Type "Type" Interface "is" (BasicType | ComplexType)

Basic Types[edit]

Basic data types have reserved names and they are inherently public to all elements of Capsula. Since these types are static, they can be implemented very efficiently, but basic types also can be used in any dynamic types.

BasicType Boolean | Integer | Real

Booleans have one bit which might be either "False" or "True".

Integers have one bit for the sign and 63 bits for the absolute value. Therefore, the extreme values are:

 Constant MinimumInteger is Public Integer -2^{63}
 Constant MaximumInteger is Public Integer 2^{63}-1

Reals are defined according to the binary 64-bit standard of IEEE 754. Integer numbers can always be used as Real numbers.

Complex Types[edit]

Complex data types are referenced by qualified identifiers and may use qualified identifiers to denote other types themselves. Complex types are very useful to contain data with complex data structures.

ComplexType QualifiedIdentifier | Array | String | Class
Arrays[edit]

Arrays denote linear lists of elements of the same data type. Its elements can be accessed by non-negative integer expressions which are called indexes. The first element is always represented by the index zero.

Array "Array" length "of" (BasicType | ComplexType)
length ConstantIntegerExpression

Capsula arrays are always one-dimensional and as structured types they cannot contain themselves but they may contain dynamic elements. The length of an array can be get by calling its read-only variable length. An array is always a dynamic data type even if its length is never changed after its first declaration because this does not affect the efficiency of the implementation.

An array with the length zero is called empty array and it has the value Nil. Empty arrays can be used to declare open arrays. An instance of an open array is created by calling the newArray-function together with a length greater than zero as an integer parameter.

ArrayDesignator Designator
ArrayTypeDesignator QualifiedIdentifier
ArrayCreation ArrayDesignator "←" "→" ArrayTypeDesignator.newArray length

The array type designator has to denote an array type by a qualified identifier and the result of the call of the newArray-function has to be assigned to an array designator of this array type.

Strings[edit]

Strings are character strings of any length and they are a fundamental data type for the software communication with human beings and all Unicode characters are allowed in strings. An empty string is always represented by the value Nil. Internally strings can be represented by arrays of integer numbers, but the user does not have direct access to the array elements.

Classes[edit]

A class comprises data (attributes) as well as code (methods) at the same time which are bound to the appropriate class. The attributes are represented by variables and the methods are represented by commands and functions. Classes can be used to inherit attributes and methods from parent classes or to pass attributes and methods on to child classes.

Classes without methods can be considered as data records. If methods of classes do not have any attributes it could be more useful and efficient to decleare these commands and functions as static commands or static functions of a module.

Class Flexibility
Extendibility
"extension of"
ParentIdentifier
{Variable}
{Command}
{Function}
Flexibility "Static" | "Dynamic"

The modifier "Flexibility" is mandatory. Static classes can be implemented more efficiently than dynamic classes, but only dynamic classes can reference themselves in recursive declarations.

Extendibility "Final" | "Extensible" | "Abstract"

The modifier "Extendibility" is mandatory. A final class cannot be extended or be abstract. An abstract class always is extensible.

ParentIdentifier QualifiedIdentifier

If the parent identifier is the class type AnyClass, which can be considered as the root class type of Capsula, then the appropriate class denotes a novel class. If a novel class is final, then it is called an elementary class, which due to the possibility of declaring not only attributes but also methods is a conceptual extension of simple data records respectively data structures.

There is a maximum of one parent identifier for a particular class, and therefore, multiple interface inheritance or implementation inheritance is neither intended nor possible nor necessary.

If classes are declared as dynamic types their attributes can be instances of or can use references to the class they belong to (recursive data structure).

An initialisation command can be bound to a class and should be called to initialise the attributes of the class (some programmers call it constructor). Usually initialisation commands have an arbitrary number of parameters, which are static for a particular class. The initialisation command of a parent class can be called within the statements of the classes’ initialisation command and therefore, it is useful to use the name of the class in the name of the initialisation command to allow easy recognition and determination of different initialisation commands. Also initialisation commands can be inherited by parent classes and therefore, they can be overwritten in child classes.

All attributes and methods are directly bound to the class and can be overwritten in extended classes, but cannot be overloaded. Therefore, their names and parameter lists are constant (this applies also for the signatures of functions) and all methods are unique for the class where they are declared as well as for any of their child classes. Nevertheless, methods of the parent classes which are not overwritten by a child class can be called for any instance of a child classes, too.

The program has to create instances of dynamic classes by calling the inherently existing newClass-function which has one parameter which denotes the name of the appropriate class:

ClassInstanceDesignator Designator
ClassTypeDesignator QualifiedIdentifier
ClassCreation ClassInstanceDesignator "←" "→" ClassTypeDesignator.newClass

The class type designator has to denote a class type by a qualified identifier and the result of the call of the parameterless newClass-function has to be assigned to an instance designator of this class type.

Variables[edit]

Variable "Variable" Signature

Variables are used to store data during run time.

Procedures[edit]

Commands as well as functions use formal parameters which are variables for exchanging data with the calling statements.

FormalParameter "Parameter" Signature

Private parameters can be considered as input parameters (call by value) and public parameters can be considered as variable or output parameters (call by reference). The definition of formal parameters is a constant list and is not affected or changed by inheritance, since Capsula does not allow overloading commands or functions. Therefore, formal parameters are not part of the interface of the commands or the signatures of functions, but of the body:

Body {FormalParameter}
{Constant}
{Variable}
{Statement}

The input parameters, constants and variables of the body are always Private, and therefore, they only can be accessed and changed locally within the statements of the body.

Commands[edit]

A command can be called as a statement.

Command "Command" Interface Body

Functions[edit]

A function can be called in an assignment statement as an expression with a result.

Function "Function" Signature Body

Expressions[edit]

Expression BooleanExpression | IntegerExpression | RealExpression | StringExpression | Designator | "Nil"

Designators are used to denote variables if complex data types and the expression Nil can be used to denote empty character strings or arrays or undefined instances of classes.

Booleans, integer and real numbers as well as strings can be used as operands.

Boolean Expressions[edit]

BooleanOperand "False" | "True" | Designator
BooleanExpression BooleanOperand | BooleanOperation

Boolean Operations[edit]

There are inherent standard public operations with Boolean operands that return Boolean values.

BooleanOperation BooleanUnaryOperation | BooleanUnaryIntegerOperation | BooleanBinaryOperation | Relation
BooleanUnaryOperation BooleanUnaryOperator BooleanOperand
BooleanUnaryOperator Not
  • The Not-operation returns the negation of the Boolean operand.
BooleanUnaryIntegerOperation BooleanUnaryIntegerOperator BooleanOperand
BooleanUnaryIntegerOperator Even | Odd
  • The Even-operation returns true if the integer operand is even and false if the integer operand is odd.
  • The Odd-operation returns true if the integer operand is odd and false if the integer operand is even.
BooleanBinaryOperation BooleanBinaryOperator BooleanOperand
BooleanOperand
BooleanBinaryOperator And | Or | Equal | NotEqual
  • The And-operation returns the conjunction of the two Boolean operands.
  • The Or-operation returns disjunction of the two Boolean operands.
  • The Equal-operator returns True if the two Boolean operands have the same values and False otherwise.
  • The NotEqual-operator returns False if the two Boolean operands have the same values and True otherwise.
Relation IntegerRelation | RealRelation | StringRelation
IntegerRelation IntegerRelationOperator IntegerOperand
IntegerOperand
IntegerRelationOperator IntegerIsEqual | IntegerIsNotEqual | IntegerIsLess | IntegerIsLessOrEqual | IntegerIsGreaterOrEqual | IntegerIsGreater
  • The IntegerIsEqual-operator returns True if the two integer operands have the same values and False otherwise.
  • The IntegerIsNotEqual-operator returns False if the two integer operands have the same values and True otherwise.
  • The IntegerIsLess-operator returns True if the first integer operand is less than the second integer operand and False otherwise.
  • The IntegerIsLessOrEqual-operator returns True if the first integer operand is less than or equal the second integer operand and False otherwise.
  • The IntegerIsGreaterOrEqual-operator returns True if the first integer operand is greater than or equal the second integer operand and False otherwise.
  • The IntegerIsGreater-operator returns True if the first integer operand is greater than the second integer operand and False otherwise.
RealRelation RealRelationOperator RealOperand
RealOperand
RealRelationOperator RealEqual | RealNotEqual | RealLess | RealLessOrEqual | RealGreaterOrEqual | RealGreater
  • The RealEqual-operator returns True if the two real operands have the same values and False otherwise.
  • The RealNotEqual-operator returns False if the two real operands have the same values and True otherwise.
  • The RealLess-operator returns True if the first real operand is less than the second real operand and False otherwise.
  • The RealLessOrEqual-operator returns True if the first real operand is less than or equal the second real operand and False otherwise.
  • The RealGreaterOrEqual-operator returns True if the first real operand is greater than or equal the second real operand and False otherwise.
  • The RealGreater-operator returns True if the first real operand is greater than the second real operand and False otherwise.
StringRelation StringRelationOperator StringOperand
StringOperand
StringRelationOperator StringEqual | StringNotEqual | StringLess | StringLessOrEqual | StringGreaterOrEqual | StringGreater
  • The StringEqual-operator returns True if the two string operands have the same values and False otherwise.
  • The StringNotEqual-operator returns False if the two string operands have the same values and True otherwise.
  • The StringsLess-operator returns True if the first string operand is less than the second string operand and False otherwise.
  • The StringLessOrEqual-operator returns True if the first string operand is less than or equal the second string operand and False otherwise.
  • The StringGreaterOrEqual-operator returns True if the first string operand is greater than or equal the second string operand and False otherwise.
  • The StringGreater-operator returns True if the first string operand is greater than the second string operand and False otherwise.

Integer Expressions[edit]

IntegerOperand Integer | Designator
IntegerExpression IntegerOperand | IntegerOperation

Integer Operations[edit]

There are inherent standard public operations with integer operands that return integer values.

IntegerOperation IntegerUnaryOperation | IntegerUnaryRealOperation | IntegerBinaryOperation
IntegerUnaryOperation IntegerUnaryOperator IntegerOperand
IntegerUnaryOperator IntegerNegation | IntegerAbsolute
  • The IntegerNegation-operation returns the negation of the integer operand.
  • The IntegerAbsolute-operation returns the absolute value of the operand parameter.
IntegerUnaryRealOperation IntegerUnaryRealOperator RealOperand
IntegerUnaryRealOperator IntegerFloor
  • The IntegerFloor-operation returns the greatest integer number less or equal than the real operand.
IntegerBinaryOperation IntegerBinaryOperator IntegerOperand
IntegerOperand
IntegerBinaryOperator IntegerSum | IntegerDifference | IntegerProduct | IntegerQuotient | IntegerModulo | IntegerMinimum | IntegerMaximum
  • The IntegerSum-operation returns the sum of the two integer operands (summands).
  • The IntegerDifference-operation returns the difference of the first integer operand (minuend) and the second integer operand (subtrahend).
  • The IntegerProduct-operation returns the product of the two integer operands (factors).
  • The IntegerQuotient-operation returns the quotient of the first integer operand (dividend) and the second integer operand (divisor).
  • The IntegerModulo-operation returns the remainder of division of the first integer operand (dividend) and the second integer operand (divisor).
  • The IntegerMinimum-operation returns the smaller of the two integer operands.
  • The IntegerMinimum-operation returns the larger of the two integer operands.

Real Expressions[edit]

RealOperand Real | Integer | Designator
RealExpression RealOperand | IntegerOperand | RealOperation

Real Operations[edit]

There are inherent standard public operations with real operands that return real values.

RealOperation RealUnaryOperation | RealBinaryOperation
RealUnaryOperator | RealOperand
RealUnaryOperator RealNegation | RealAbsolute
  • The RealNegation-operation returns the negation of the real operand.
  • The RealAbsolute-operation returns the absolute value of the real operand.
RealBinaryOperation RealBinaryOperator RealOperand
RealOperand
RealBinaryOperator RealSum | RealDifference | RealProduct| RealQuotient | RealMinimum | RealMaximum
  • The RealSum-operation returns the sum of the two real operands.
  • The RealDifference-operation returns the difference of the first real operand (minuend) and the second real operand (subtrahend).
  • The RealProduct-operation returns the product of the two real operands.
  • The RealQuotient-operation returns the quotient of the first real operand (dividend) and the second real operand (divisor).
  • The RealMinimum-operation returns the smaller of the two real operands.
  • The RealMaximum-operation returns the larger of the two real operands.

String Expressions[edit]

StringOperand String | Designator | "Nil"
StringExpression {StringOperand}

Nil denotes an empty String. Strings can be concatenated by easily putting them one after another.

Statements[edit]

The difference between commands and functions is that the former do not have return values which have to be assigned to a desigator. Commands are called as a statement and functions are called as an expression within an assignment statement. Both, commands and function, use parameters to exchange data with the calling statement.

ActualParameter Expression

The actual parameters of a command or function call must have exactly the same number and assignment compatible data types as the formal parameters of the called command or function.

Since function calls are not considered as expressions in Capsula, actual parameters cannot be results of function calls directly, because nested function calls may cause side effects which depend on the sequence of the actual parameters. Therefore, the results of function calls have to be assigned to designators which then can be used as actual parameters of a command or function call.

Call "→" Designator {ActualParameter}

A method or the init-command of a parent class can be called within a method or the init-command of a child class (super call).

There are four differend kinds of statements:

Statement CommandCall | Assignment | Branch | Loop

Command Calls[edit]

CommandCall Call

There are a few standard public commands:

Halt Command[edit]

If the Halt-command is called, the program exeution stops at this particular point of the statement sequence.

Boolean Commands[edit]

The value of a Boolean variable (also within arrays or classes) can be flipped by the Flip-command with one Boolean parameter.

Integer Commands[edit]

The value of an integer variable (also within arrays or classes) can be decreased by one by the Decrease-command and increased by one by the Increase-command. Both commands have exactly one integer parameter.

Assignments[edit]

Assignment Designator "←" Expression | FunctionCall

Any expression can be assigned to a designator which is assignment compatible to the expression.

FunctionCall Call

Functions only can be called within assignments. The result of a function has to be assigned to the designator of the assignment. Therefore, the result of the appropriate function also must be assignment compatible to the data type of the designator.

Branches[edit]

Branch BooleanBranch | IntegerBranch | TypeBranch

Boolean Branches[edit]

BooleanBranch "If" BooleanExpression TrueStatements
FalseStatements
TrueStatements "True→" {Statement}
FalseStatements "False→" {Statement}

Integer Branches[edit]

IntegerBranch "If" IntegerExpression "is" {IntegerCase}
IntegerElse
IntegerCase ConstantIntegerExpression "→" {Statement}
IntegerElse "IntegerElse→" {Statement}

Type Branches[edit]

TypeBranch "If" Designator {TypeCase}
TypeElse
TypeCase ConstantTypeExpression "→" {Statement}
TypeElse "TypeElse→" {Statement}

Within the statement sequence of a type case the variable denoted by the designator will be treated as a variable of the appropriate constant type of the type case.

Loops[edit]

Pre-test and post-test loop conditions are locally linked to the loop as Boolean operands. These loop conditions have to be considered as local and private variables of the loop, and therefore, they cannot be accessed outside of the Loop statement.

LoopCondition "←" BooleanOperand

The statement sequence of a loop statement will only be invoked and repeated as long as the loop condition is "True". The pre-test loop condition has to be given in the first statement of the loop. The post-test loop condition has to be given as the last statement of the loop.

Loop "While" LoopCondition "→" {Statement}
LoopCondition

If the pre-test loop condition is set to "True", then the statements within the loop will be executed at least once. If the pre-test condition is set to "False", then the statement sequence will not be executed at all.

Examples[edit]

Hello World[edit]

The quasi standard programme "HelloWorld" can be graphically expressed in Capsula like this:

HelloWorld.cap.png

The command can be invoked within the scope of the package "Examples" by calling the symbol Examples.HelloWorld.printHelloWorld and will print the string "Hello World !" to the standard output of the system.

If there are no parameters in a command, the appropriate frame is kept empty in the code. The constant string "OutputString" is private and can only be used within the procedure of the command "printHelloWorld". Since strings do not need delimiters in Capsula such as quotation marks, the background rectangle of the string is marked by a colour. Because there are no local variables in the procedure, the appropriate frame is hidden.

All sub frames optionally can be edited separately in a new window by clicking on the the hyperlink of the appropriate identifier in the left upper field of the sub frame, where the sub frame always is extended to the uttermost right edge of the structure. Clicking on "Hello World" produces a new window like this for example:

HelloWorld.Module.cap.png

All sub frames can be reduced in the editor to one line or extended with clicking on the name of the appropriate Capsula element. For example clicking on "Module" produces the following display with the collapsed frame of the module:

HelloWorld.collapsed.cap.png

The definition view of a Capsula element only shows all public items:

HelloWorld.definition.cap.png

Recursive factorial[edit]

A recursively defined function factorial in a module IntegerMath of the package Examples that computes the factorial of an integer number could be defined like this:

IntegerMath.cap.png

If you call the function factorial with the integer parameter x with the value 6 you will get returned the integer value factorial 720.

About[edit]

The naming of Capsula refers to the fact that it strictly and strongly supports the principles of encapsulation.

But at the same time the name Capsula is a hidden dedication to several programming languages which have influenced Capsula. The name Capsula contains all letters of the names of the programming languages APL, C and Pascal. Furthermore, it ends with "-ula" such as the programming language Modula and it has an "a" at the second and at the last position such as the programming language Java.

The seed of the idea to invent Capsula was a interview of Niklaus Wirth at the IEEE Computer Society for the medium Computing Now in 2010. He was asked:

„You mean they should go back and start designing a new language.“,

and he responded:

„Well, they could go back to Oberon and start there and improve it.“

Antoine de Saint-Exupéry has written in the third chapter L'Avion of his book Terre des hommes:

„Il semble que la perfection soit atteinte non quand il n'y a plus rien à ajouter, mais quand il n'y a plus rien à retrancher.“
(„It seems that perfection is not attained when there is nothing more to add, but when there is nothing more to remove.“)

Johann Wolfgang von Goethe has written the poem Das Sonett which ends with these six lines:

So ists mit aller Bildung auch beschaffen:
Vergebens werden ungebundne Geister
Nach der Vollendung reiner Höhe streben.
Wer Großes will, muß sich zusammenraffen;
In der Beschränkung zeigt sich erst der Meister,
Und das Gesetz nur kann uns Freiheit geben.
(That is the apperance of all education:
Free spirits will aspire in vain
to the pure summit of accomplishment.
The one who wants great things, has to gather himself;
The master presents himself by limitation,
And only law can give us freedom.)

Therefore, the stepwise refinement during the development of Capsula often was rather a stepwise coarsening respectively simplification than a refinement. But this was always done without removing any essential power of the programming language.