-
-
Notifications
You must be signed in to change notification settings - Fork 26
ELENA in a nutshell
ELENA is a general-purpose language with late binding. It is multi-paradigm, combining features of functional and object-oriented programming. It supports both strong and weak types, run-time conversions, boxing and unboxing primitive types, direct usage of external libraries. Rich set of tools are provided to deal with message dispatching : multi-methods, message qualifying, generic message handlers. Multiple-inheritance can be simulated using mixins and type interfaces. Built-in script engine allows to incorporate custom defined scripts into your applications. Both stand-alone applications and Virtual machine clients are supported.
Here we will learn ELENA in details. Let's start!
To create a simple program in ELENA we have to create a source file (with an extension .l) and write the following code:
public program()
{
console.writeLine("Here my first program in ELENA!")
}
We may compile it without creating a project file (where elc is a command-line compiler):
elc program1.l
The output is:
ELENA Command-line compiler 5.2.404 (C)2005-2020 by Alex Rakov
Project : program1, Platform: STA Win32 Console
Cleaning up...
Compiling...
Parsing unnamed
Compiling unnamed
Successfully compiled
Linking...
Successfully linked
It will create program1.exe file which we can execute:
program1
with the following result:
Here my first program in ELENA!
Beside the executable file a module unnamed.nl was created. Let's look what inside. We could use Bycode Viewer:
ecv unnamed.nl
The output will be:
ELENA command line ByteCode Viewer 5.2.81 (C)2011-2020 by Alexei Rakov
unnamed.nl module loaded
>
Now let's look at the generated classes:
>?
class program
>
As you can see the program entry was compiled as a class. Let's look inside:
>program
@parent system'Object
@flag elSealed
@flag elStateless
@flag elRole
@method @function program.#invoke
>
Our function was compiled as a singleton with a single anonymous method #invoke. Let's dive more deep:
>program.1
@method program.#invoke
open 1h
pusha
pushr 0
pushr 0
callr system'console
storesi 0
movr const : "Here my first program in ELENA!"
storesi 1
peeksi 0
movm mssgconst : "writeLine<system'String>[2]"
callrm system'$private'Console mssgconst : "writeLine<system'String>[2]"
peekfi 1
close
quit
@end
>
What do we see? ELENA byte-codes are quite simple. Let's review some of them
opcode | Description |
---|---|
pusha | puts the object accumulator on the top of the function stack |
pushr r | puts a constant on the top of the function stack |
callr r | invokes a symbol |
storesi i | saves an object accumulator in the function stack at specified relative position |
movr r | assigns a constant to the object accumulator |
peeksi i | loads an object from the function stack at specified relative position to the object accumulator |
movm m | assigns a message constant to the data accumulator |
callrm r m | invokes a method m in r class |
Once again let's look at our code. Now it is quite clear. We put console symbol and a string literal constant into the function stack and directly invokes system'$private'Console.writeLine<system'String>[2] method.
Is our program executed at the executable start? Let's look into the linker code:
// create the image
ident_t entryName = project->resolveForward(SYSTEM_ENTRY);
_entryPoint = emptystr(entryName) ? LOADER_NOTLOADED : linker.resolve(entryName, mskSymbolRef, true);
if(_entryPoint == LOADER_NOTLOADED)
throw JITUnresolvedException(ReferenceInfo(SYSTEM_ENTRY));
where SYSTEM_ENTRY is defined as:
constexpr auto SYSTEM_ENTRY = "$system_entry"; // the system entry
So the answer is no. There is a special entry which executes initialization code and invokes our program. The system entry is a symbol. Can I redefine it? Yes of course. Let's look at our code once again: $system_entry is resolved as a forward. What is a forward. In ELENA the forward reference is a reference which is resolved in linking-time. It means that this information should be provided when we compile our project.
Let's do it! We will provide a default exception handler to gracefully end the program in case of an error:
// system entry
public mySystemEntry = startUp();
// system boot code
startUp()
{
try
{
// invoking a program entry
program()
}
catch(Expression ex)
{
console.writeLine(ex.toPrintable())
}
}
// a program entry
public program()
{
console.writeLine("Here my first program in ELENA!")
}