FunLog++ - introduction - glossary - language - library - special - semiknown - dynamic
FunLog++ Language
FunLog++ startup - syntax - message - semantic - object - command - identification

FunLog++ system start-up

The FunLog++ system currently is implemented as the FunLog++ interpreter (FUN.EXE) which consists of two subprograms, the FunLog++ compiler (FUNC.EXE) and the FunLog++ executer (FUNX.EXE). The compiler translates a FunLog++ source file, say HEPATITIS.FUN, into an intermediate file, then HEPATITIS.LPA. The FunLog++ executer loads the intermediate file and generates an output file, then HEPATITIS.RES.

The FunLog++ interpreter call

sends the command root("hepatitis"):reportto the FunLog++ runtime system. Due to the message root("hepatitis") the interpreter loads file HEPATITIS.LPA and make available its root object. Then the message, e.g. report, is sent to this root object. Regard the point (.) behind the parameter which is needed by the compiler and the interpreter in the current implementation. When FUN.EXE execution has finished there is a new file HEPATITIS.RES which contains the text obtained by evaluating the command report. The FunLog++ compiler will be called automatically if there is no suitable *.LPA file or if this intermediate file is older than a present source file *.FUN.


FunLog++ syntax

FunLog++ syntax is described formally in a two level grammar of syntactic rules. A syntactic rule consists of syntactic variables (begin with a small letter, e.g. method body), and terminal symbols (given in double quotes, e.g. "::="). Double colon :: separates grammar rule handle from grammar rule body. In the grammar body semicolons separate alternative constructs whereas commas are used to concatenate constructs. In order to describe operator precedence formally in this grammar a second (meta-)level was introduced, the meta parameters. If required, meta-parameters are written in round brackets immediately behind the syntactic variables, e.g. operand(Priority-1). Meta-parameters are meta-variables, text constants, numeric constants, or terms of meta-parameters. Meta-variables begin with a capital letter.

FunLog++ syntax is very simple. A FunLog++ program is a sequence of functions. A FunLog++ function is either a method, an inlay or a class. Methods and classes are syntactically very similar as both consist of a receptor, a public (::=) or private (::-) is-defined-as symbol, a method body or a function body, and a finishing point. The bodies of classes and methods are different. A class body begins with a curly opening bracket, followed by a sequence of (sub-)functions, and is finished by curly closing bracket. A method body, in contrast, is a message which is a functional, a formula, an atomic, a constant, a list, or a variable. A third sort of function is an inlay which looks like a receptorless method. Inlays define inheritance links between objects.

We introduce the notion of rootclass for a (invisible) class comprehending all programs of different FunLog++ source files belonging to an application. We call a function A to be an element of class B if A is in the function list of the program of B.

As classes may contain other (sub-)classes we get a static class hierarchie. This hierarchie allows an absolute or relative denotation of any function by an appropriate message.

The signature of a receptor or message is its name plus its arity (number of parameters). A function is suitable to a message if  its receptor signature is the same as the message signature. An inlay function is suitable to all messages. Private functions are only visible to messages from within the same class, public functions are visible to all messages.

A functional consists of an atom (the function name), and a list of parameters in round brackets. All receptors and messages with parameters may be written as a functional. But additionally a predefined set of names (operators) is enhanced by prefix, infix, and postfix capabilities which includes an operator type and an operator priority. An operator is a special atom which additional attributes in order to enhance syntactic sugar. With each operator name, operator-type, and -priority are defined for syntax analysis. The operator type determines if it may occur in an prefix position (fx), an infix position (xfx, xfy, yfx), or an postfix position (yf). While f stands for the operator, x and y stand for the operands. An x-operand states that in this position only formulas with a lower priority are allowed. An y-operand states that formulas with lower or equal priority are possible. In the grammar x-operand have priority P whereas y-operands have priority P-1. So e.g. X+Y+Z is allowed whereas X=Y=Z is not since operator + is of type yfx whereas operator = is of type xfx. But in any case round brackets may be used in order to specify message structure. For all operators functional notation is allowed too, e.g. +(+(X,Y),Z) is also correct (but some unreadable) instead of X+Y+Z.
 
  A formula is a prefix formula, an infix formula, or a postfix formula. Prefix- and infix formulas are mainly used to implement control functions and arithmetic functions. Postfix formulas are used to represent dimensional units.

A list is a data structure, e.g. [3,5,7,11], which is used to represent an ordered sequence of arbitrary objects. A list may be seen as one or more head element followed by a list of tail elements. There is also a denotation, e.g. [3,5,7,11,|MORE], where the list of tail elements is a variable, e.g. MORE. List objects are enclosed in square brackets. Number of list elements may increase as long as the sublist of tail elements is a variable. [ ]is the empty list denotation which has no elements. Comment: Due to an error in the current FunLog++ compiler version it is important to have at least one character (e.g. a blank) between [ and].

The syntax of a constant, an atom, and a variable name is defined informally as follows:

The following three tables relate operator symbol with its type (fx, xfx, xfy, yfx, xf) and its priority (an integer between 0 and 12). Operators with high priority numbers bind loose while operators with low priorities bind tight. In the first table operators for control-, unification-, and ordering functions are shown:

Regard that comma (,) and vertical bar (|) may also appear in special locations where they do not serve as an operator but as an delimiter: In a parameter list, e.g. myfunction(A,B,C), commas separate parameters and in an object list, e.g. [3,5,7,11] commas separate list elements. Furthermore, in an object list, e.g.[H1,H2,H3|Tail], the vertical bar is used to separate head elements form the tail element list. That is why a parameter is an operand of a priority less equal 9. If an operand of priority 10, 11 or 12 is wanted in a parameter position then it has to be written as a block with an extra pair of round brackets, e.g.myfunction((A\/B)).

In the following table operators for concatenation, arithmetic, and interval construction are listed:

The following table lists postfix operators of priority 1. They are used to define syntax for dimensional units in measure expressions. Operator type yf determines that dimensional unit may be queued, e.g. 28 kg m.

FunLog++ semantic

In this chapter the runtime behaviour of a FunLog++ program is described. The runtime behaviour of standard library functions is described in the document "standard library". Also most control functions (e.g. ,/2 and ;/2) are described there. Different target platform and target language features are described in the document "target platform and language". In the next chapters there follows a description of specific relation between classes: inner classes and parent classes. In order to access functions from inner and outer classes the selection operator:/1 and:/2 is described here. The name space of a function is usually the program of its class, i.e. its neighbour functions within its class. But the name space is extended to parent classes by inheritance with so called inlay functions. If a message has no definition in its name space then a second level of identification applies, the parameter oriented identification.

Object and Command

An object is a data structure at runtime. It is determined by a specific class in a FunLog++ program plus actual class parameters which are objects in turn. There are two system classes for numbers and texts. They have one primitive number and text value class parameter respectively. In FunLog++ objects have no internal state and so its function is completely defined by its class and its actual parameters.

command is also a data structure at runtime. It is determined by a specific message in a FunLog++ program plus its actual parameters which are objects or commands. An object is obtained as the final result of the evaluation of a command, the resulting object of that command. So a command is equivalent with its resulting object. It is in some sense a not (or not completely) evaluated object. Commands are important for lazy evaluation. A command is the runtime equivalent of the compiletime construct message.


 Static Class Hierarchy

A FunLog++ program is a set of partial functions. The set of functions is ordered in a static class hierarchy. The topmost class is called the rootclass. All other classes of a FunLog++ program are direct or indirect subclasses of the rootclass. Classes may contain subfunctions which are (sub)classes or (sub)methods. Subclasses are also called inner-classes. The syntactically containing class of some function in the FunLog++ source file is called its super-class (not to confuse it with the parent-class which is defined by inheritance). In FunLog++ the superclass/subclass relation is used to identify functions. Inner-classes were introduced in FunLog++ in order to hide them against external access.
 
 
 
(01)
  alpha ::= {
(02)
(03)
    beta ::= {
(04)
      delta ::= "Hello world".
(05)
      ... further functions of class beta ...
(06)
      }.
(07)
(08)
    omega ::= beta:delta.
(09)
    ... further functions of class alpha ...
(10)
    }.
 
 
 
    Super-sub-class relation:
    alpha/0 is super-class of beta/0 beta/0 is sub-class of alpha/0
    Class beta/0 is one of the functions of alpha/0
    The result of message omega is "Hello world".
Functions are identified by a function identifier which consists of the identifier of the containing superclass, the function name, and the function parameters. Function identifiers are used in messages where a colon separates the class identifier from the subfunction. E.g. :standard:number(N):display(T)is the identifier of a method with the name display, with one parameter T, and which is contained in class :standard:number(N). Here :standard:number(N)is the identifier of subclassnumber(N)which is contained in class:standard which itself is contained in the rootclass. The containing class may be omitted in a message if it is the class of the message. Direct subfunctions of the rootclass are recognised by a preceding colon, e.g.:standard.

A receiving class may also be calculated during evaluation. E.g. X:display(T) is subfunction display(T) in the receiver X whereX has to be a known object at the time of evaluation of  X:display(T). In FunLog++ it is not possible to calculateX during evaluation of X:display(T). But the following message is legal: X = :standard:number(N), X:display(T).

From within a function receptor (the handle) or from within a message we can refer to the surrounding class object be the reserved Variable name SELF. But in FunLog++ it is not possible to calculate some object in the superclass of some object X. (We could want to write X:..:alpha to denote some object alpha in the superclass of X.)

The user of some function need not to know if it denotes a class or a method. In any case he/she gets the parameters and the result unified with appropriate objects. Thus methods may be used to rename or shortcut other methods or classes. That is why FunLog++ syntax is so simple.


Dynamic Class Hierarchy

There is a second class hierarchy which is obtained when classes are related by inheritance. In FunLog++ inheritance serves to separate functions which are common to several classes. Furthermore inheritance may also be used in order to extent a classes name space to functions which are stored in a different location, e.g. on a different computer.
 
 
(01)
  alpha ::= {
(02)
    omega ::= delta.
(03)
    ... further functions of class alpha ...
(04)
    ::= :gamma.
(05)
    }.
(06)
(07)
  gamma ::= {
(08)
    delta ::= "Hello world".
(09)
    ... further functions of class gamma ...
(10)
    }.
 
 
 
    Parent-child-class relation:
    alpha/0 is child-class of gamma/0 gamma/0 is parent-class of alpha/0
    Class alpha/0 inherits from class gamma/0 by the inlay function ::= :gamma.
    The result of message omega is "Hello world".
A command (=function call) is evaluated in two steps. First a suitable and acceptable function definition has to be found in its name space or in the name space of one of its parameters. Second, if the found function is a method then the method body has to be evaluated. If that function is a class then the object defined by this class is returned.

A command is suitable to a function if name and arity (=number of parameters) are equal. A command is acceptable to a function if there is no failing gate condition. Class definitions have no gate conditions and so always accept. A method definition accepts a command if the evaluation of the method body does not return the missing/0 object. The missing/0 object is not visible to the programmer but it is internally used to find the suitable function definition. The missing/0 object is generated if the left hand operand of the gate operator fails, i.e. if A fails in  A | B. As non variable formal method parameters are converted using the gate operator |/2 , unsuccessful pattern matching also generates a missing/0 object. E.g.
 say("red")    ::= "The colour is red".
 say("yellow") ::= "The colour is yellow".
 say("green")  ::= "The colour is green".

The three function definitions of say/1 is converted internally by the FunLog++ compiler to a function

 say(X) ::=     X="red"    | "The colour is red"
            ::  X="yellow" | "The colour is yellow"
            ::  X="green"  | "The colour is green".

The formal parameter X is tested by unification if it is red, yellow or green. The ::/2 operator returns its left operand if this is not missing/0, otherwise it returns its right operand. The command say("blue") will be suitable to say/1 as it also has one parameter. But as the gate condition fails for all alternatives, this say/1 method definition will return missing/0.

If there is no suitable function or if a suitable function definition is not acceptable then inheritance is tried. That means that if there is a inlay function then its body is evaluated returning a receiver object. Then the command is tried to be identified in the program of that receiver object. If local identification and inheritance fail then the so called parameter oriented command identification is tried.


Parameter oriented command identification

This second technique of command identification allows to find the function definition of some message without having it in the same context and without applying inheritance. This is a very important feature of FunLog++ as all standard library functions are identified this way. In contrast to most other object oriented languages FunLog++ functions are not identified by explicit class selectors or by inheritance.

If context oriented command identification fails then the command's parameter list is evaluated. If there are parameters then the first parameter is evaluated. Then the class of the obtained parameter object is tried as a context to find a suitable, fitting and acceptable function definition. If the first parameters does not work then the next parameter is tried, and so on.  If the command has no parameters at all then the system class atomic/0 is tried as a last choice. If neither a parameter's class nor class atomic/0 worked then the system exception object exception("function undefined",Source) is returned.

With parameter oriented command identification a further condition has to be fulfilled. The parameter position used for the new identification context  must fit the function definition, i.e. the function in question must have a formal parameter called SELF in the appropriate position. E.g. in the standard library class number/1 there is a method sqrt/1 which only can be identified through its parameter.

  number(A)  ::=  {
    ...
    sqrt(SELF)   ::=  power(A,0.5).
    ...
    }.

Or as a second example in standard library class list/1 the method member/2 is identified through its second parameter which always is a list.

  list(A)  ::=  {
    ...
    member(_,SELF)       ::=  SELF = [ ]      | failure.
    member(ELEM,SELF)    ::=  SELF = [Head|_] | ELEM == Head.
    member(ELEM,SELF)    ::=  SELF = [_|List], member(ELEM,List).
    ...
    }.

Finally parameterless commands may be identify their method in the system class atomic/0. E.g. the message pi/0 may be calculated that way.

  atomic ::= {
   ...
   pi       ::= 3.14.
   ...
   }.

A important consequence of this technique of parameter oriented command identification is, that a FunLog++ programmer needs no knowledge about the internal structure of the standard library nor about its class names. This works as the FunLog++ compiler recognizes the type of number, text, and list denotations and it then generates code to build up an object of the appropriate class. So a command like sqrt(pi) can easy be evaluated as first pi/0 is found in class atomic/0 and then sqrt(3.14) is found in class number/0. No class selector and no inheritance is needed for that.


 Evaluating the message body

In FunLog++ messages are sent to an object in order to be evaluated. During evaluation actual message parameters and message result are unified with formal function parameters and result. The function being accepted for message evaluation has to be identified by a FunLog++ specific search strategy which is described above. From the viewpoint of a candidate function it has to check if it can accept the message for evaluation. A message is accepted if the (partial) function is defined for this message, i.e. if the tuple of actual message parameters is in the function's.
 
 
FunLog++ - introduction - glossary - language - library - special - semiknown - dynamic
Last modification: B. Pohl 15. September 1997 / 27.August 2000 / 18.Oktober 2000