Saturday, January 15, 2011

ELENA Programming Language:method calling syntax

In this post I would like to make a short overview of ELENA method syntax features (starting from 1.5.6.9 version).

ELENA programming language (unlike many others) introduces several limitation on the programmer free will over naming and using methods. First of all the method can have only one parameter. Secondly there are special rules how the method could be named (apart from private ones, which we will ignore in this post).

The simplest method declaration may look like this (in case of in-line class, the keyword is omitted):
#method subject'verb : parameter
[
]



As you see the method name consists of two parts: a subject (a noun) and a verb. The verb defines an expected operation, the subject describes a method parameter (a list of possible operations with it).
If the message do not have a subject part it is considered to be generic (and can be used for multi-dispatching). The 'GET' messages may omit their verbs. The following expressions are equivalent: “aNumber int'get” and “aNumber int” (“int” is a subject).

There are a limited list of verbs in ELENA (though this lists will be expanded with the time, to avoid possible verb overuse). Let's name them: add, and, append, back, check, clear, clone, close, delete, dispatch, divide, do, equal, evaluate, find, free, get, greater, if, ifequal, ifless, ifnot, increase, insert, is, isnot, less, load, multiply, new, not, notequal, notgreater, notless, open, or, proceed, process, react, read, reduce, repeat, rewind, run, save, send, separate, set, start, stop, subtract, wait, write, xor.

There are synonyms (operators) for some verbs. Unlike normal verbs, operators have lower parsing order. These codes are equivalent - “a << b + c int'get” and “a write:(b add:(c int'get))”. Operatiors are generic verbs and cannot have subjects. Let's name the operators and their verbs:
== - equal,
!= - notequal,
>= - notlesss,
<= - notgreater,
> - greater,
< - less,
? - is,
! - isnot,
@ - seek,
=> - evaluate,
>> - read,
<< - write,
+ - add,
- - subtract,
* - multiply,
/ - divide,
+= - append,
-= - reduce,
*= - increase,
/= - separate

Unlike verbs the subject names are not limited (it is not recommended to give a name equal to a verb, because of possible ambiguity). But the subject should be declared before the use. The syntax looks like this:
#subject subject, argument1, argument2.

It is possible to import subjects declared in another packages (the subjects declared in the project are automatically imported in all following modules).

#subject math'dictionary'*.


If there is a name conflicts between subjects declared in different modules it is possible to provide an alias (will be implemented in 1.6.0).

#subject math'* = math'dictionary'*.


It is possible to import the subjects to the whole project (std'dictionary, std'dictionary'protocols, std'dictionary'types subjects are imported automatically to any program or library).

Though the method may have only one parameter it is still possible to provide several arguments with the help of argument objects. Let's consider how we could declare the method with an argument list.

#method subject'verb &argument1:anArgument1 &argument2:anArgument2
[
]



This code will be compiled into the following:

#method subject'verb  : anArguments
[
#var anArgument1 := anArguments argument1'get.
#var anArgument2 := anArguments argument2'get.
]



The similar syntax could be used for passing multiple arguments to the method (note that it doesn't matter if the method declaration uses an argument list).

anObject subject'verb &argument1:anArg1 &argument2:anArg2.


This code will be compiled into the following:

anObject subject'verb: { argument1'get = anArg1. argument2'get = anArg2 }.


As it was already said above the subject defines the method parameter. This feature is used in ELENA for implementing multi-dispatching.

Let's declare three classes A, B, C and assigns subject1 to the class A, subject2 to the class B (class C does not have assigned subject).

#hint(subj:subject1)
#class A
{
}

#hint(subj:subject2)
#class B
{
}

#class C
{
}



Now we will declare the fourth class which will deal with them.

#class D
{
#method subject1'set : anObject [ … ]

#method subject2'set : anObject [ … ]

#method set : anObject [ … ]
}



We are going to call the verb set with instances of classes A, B and C. According to our notation for the instance of the class A we have to call subject1set, for an instance of B – subject2'set. Because the class C does not have an subject we should call generic method set (it is expected that the generic methods are able to work with “unknown” objects). So lets declare three variables and call the appropriate methods.

#var anA := A.
#var aB := B.
#var aC := C.

D subject1'set:anA subject2'set:aB set:aC.



But in most cases we do not know its type (in ELENA its class or supported subject). It is possible dynamically resolve the appropriate message. Let's add a special attribute to the generic method.

 #hint(disp)
#method set : anObject [ … ]



Now we could simplify the code and the appropriate message will be called automatically

D set:anA set:aB set:aC.


And finally let's consider the concept of an argument signature. A signature allows to define the message subject on the base of argument list (static multi-dispatching).

Let's presume we have a following argument list

#method subject'set &argument1:anArg1 &argument2:anArg2 &argument3:anArg3 […]


Instead of passing every time all three arguments we could define three alternative argument signature: &argument1 & argument2, &argument2 & argument3 and &argument1 & argument3.

#hint(subj:subject, signature:(argument1, argment2), signature:(argument2, argment3), signature:(argument1, argment3))
#class CustomArgumentList
{
#hint(arg:argument1)
#field theArg1.

#hint(arg:argument2)
#field theArg2.

#hint(arg:argument3)
#field theArg3.

#method argument1'get = theArg1 nil'isnot | back:0.

#method argument2'get = theArg2 nil'isnot | back:0.

#method argument3'get = theArg3 nil'isnot | back:0.
}



(Note that the signature class, should be declared in the same module where the first argument is declared). The mapping between argument value and a signature class field is defined by arg hint.

So now we could use simplified syntax to call subject'set

anObject set &argument1:anArg1 &argument2:anArg2.
anObject set &argument2:anArg2 &argument3:anArg3.
anObject set &argument1:anArg1 &argument3:anArg3.



Note that the order of the argument subjects play important role. &argument2 &argument1 and argument1 &argument2 are different signatures.

If the argument list contains only one argument it will be automatically translated into an appropriate message.

anObject argument1'set:aParam and anObject set &argument1:aParam are equivalent.


The signature cannot be used in the method declaration. If no appropriate signature can be found the generic method will be called.

No comments:

Post a Comment