Category:Elena: Difference between revisions

From Rosetta Code
Content added Content deleted
mNo edit summary
 
(30 intermediate revisions by the same user not shown)
Line 12: Line 12:
ELENA is a general-purpose, object-oriented, polymorphic language with late binding. It features message dispatching/manipulation, dynamic object mutation, a script engine / interpreter and mix-ins.
ELENA is a general-purpose, object-oriented, polymorphic language with late binding. It features message dispatching/manipulation, dynamic object mutation, a script engine / interpreter and mix-ins.


* ELENA on [https://github.com/ELENA-LANG/elena-lang/wiki/ Github]
== The simplest program ==

To create a simple console program we have to declare the **program** symbol in the project root namespace:

program =
[
].

Everything in ELENA is an object. To interact with it we have to send a message. The simplest (*generic*, i.e. without an explicit signature) message consists of *an action* and a *parameter list*.

The statement should be terminated by a dot (*ELENA is inspired by Smalltalk and uses its syntax notations*).

program =
[
console writeLine("Hello!").
].

In our example the action is **writeLine** and the parameter list consists of a single literal constant. The message target is **console** object (implementing input / output operations with a program console).

Several message operations can be done in a single statement separated by a semicolon:

program =
[
console writeLine("Hello!"); writeLine("How are you?").
].

The result will be:

Hello!
How are you?

We may read a user input by sending **readLine** message without parameters:

program =
[
console write("What is your name:"); writeLine("Hello " + console readLine).
].

The result will be:

What is your name:Alex
Hello Alex

_Console::write_ method is similar to _writeLine_ except that it writes to the output screen without a new line character.

== Declaring a variable ==

A variable can be declared in an assignment statement starting with **var** attribute:

var myVariable := "A text".

where we declare a variable **myVariable** and initialize it with a literal constant value.

The assigning value can be an expression itself:

program =
[
console writeLine("Hello!"); writeLine("How are you?").
var s := console readLine.
].

ELENA is a dynamic language and in normal case we may not specify the variable type:

program =
[
var s := "Hello".
console writeLine(s).

s := 2.
console writeLine(s).
].

The output will be:

Hello
2

But it is still possible to specify the variable expected type:

type<LiteralValue> s := "Hello".
console writeLine(s).

*where system'LiteralValue is a class representing text as a sequence of UTF-8 characters.*

We may use a class alias to simplify the code:

literal s := "Hello". // literal is a LiteralValue alias
console writeLine(s).

Note that despite it we may still assign the objects of different types without a compile-time error:

literal s := "Hello".
s := 2.

Why? ELENA is a dynamic language and in most cases resolves the types in run-time. So our code will be actually
compiled as follow:

literal s := "Hello".
s := 2 literal.

It is guaranteed that the result of **literal** message is an instance of LiteralValue, so if the object supports the message the conversion will be done quietly. In fact this code will work because **IntNumber** supports this conversion. But the following code will be broken in run-time:

int n := 3.
n := 3.4r.

The output will be:

system'RealNumber : Method $system'IntNumber not found
Call stack:
system'Exception#class.new$system'LiteralValue[1]:exceptions.l(125)
system'MethodNotFoundException#class.new$system'Object$system'Message[2]:exceptions.l(213)
system'#inline1BF.start[1]:win32_app.l(252)
mytest'program.#invoke[0]:test.l(5)
system'BaseFunction.eval[0]:control.l(172)
system'#inline1BF.start[1]:win32_app.l(37)
system'startUp(5)
== Basic Types ==

=== The Boolean Type ===

Boolean type is used in conditional operations and may accept only two Boolean literals - **true** and **false**.

import extensions.
program =
[
bool b1 := true.
bool b2 := false.
console printLine(b1,"==",b1," is ",b1==b1).
console printLine(b2,"==",b2," is ",b2==b2).
console printLine(b1,"==",b2," is ",b1==b2).
console printLine(b2,"==",b1," is ",b1==b2).
].

*Note that implicit extension method - **extensions'outputOp.printLine[]** - was used to simplify the output operations.*

The output is:

true==true is true
false==false is true
true==false is false
false==true is false

=== The Numeric types ===

The most used numeric types in ELENA are 32-bit signed integer number (represented by **IntNumber**), 64-bit signed integer number (represented by **LongNumber**) and 64-bit floating-point number (represented by **RealNumber**):

import extensions.
program =
[
int n := -234.
long l := 1235456765l.
real r := 2.3456r.
console printLine("Integer number - ",n).
console printLine("Long integer number - ",l).
console printLine("Real number - ",r).
].

The output is:

Integer number - -234
Long integer number - 1235456765
Real number - 2.3456

=== The string Type ===

**LiteralValue** is used to store the text encoded in UTF-8. LiteralValus is read-only collection of **CharValue** classes each representing UTF-32 symbol. *Note that one character may be encoded with more than one byte!*.

import extensions.
program =
[
var s := "Hello".
console printLine("The first character of ",s," is ", s[0]).
console printLine("The last character of ",s," is ", s[s length - 1]).
].

The output is:

The first character of Hello is H
The last character of Hello is o

The same code for example with a Russian text will not work. Because every character is encoded with a two bytes and this should be taken into account.

import extensions.

program =
[
var s := "Привет".
console printLine("The first character of ",s," is ", s[0]).
console printLine("The last character of ",s," is ", s[s length - 1]).
].

The output is:

The first character of Привет is П
An index is out of range
Call stack:
system'Exception#class.new$system'LiteralValue[1]:exceptions.l(125)
system'OutOfRangeException#class.new[0]:exceptions.l(149)
system'LiteralValue.getAt$system'IntNumber[1]:memory.l(1191)
mytest'program.#invoke[0]:test.l(8)
system'BaseFunction.eval[0]:control.l(172)
system'#inline1BF.start[1]:win32_app.l(37)
system'startUp(5)

We may use another class representing UTF-16 text (**WideLiteralValue**) to solve this problem:

import extensions.
program =
[
var s := "Привет"w. // UTF-16 string
console printLine("The first character of ",s," is ", s[0]).
console printLine("The last character of ",s," is ", s[s length - 1]).
].

The output will be correct this time:

The first character of Привет is П
The last character of Привет is т

But this code will not work with Chinese text or any other requiring more than 2 bytes per symbol. So instead we may use enumerators:

import system'routines.
import extensions.
program =
[
var s := "Привет".
console printLine("The first character of ",s," is ", s enumerator; firstMember).
console printLine("The last character of ",s," is ", s enumerator; lastMember).
].

The output will be correct for any UTF-8 text:

The first character of Привет is П
The last character of Привет is т

=== Array type ===

It is possible to declare a dynamic or static array.

import extensions.
program =
[
var staticArray := (1,2,3).
var dynamicArray := Array new(3).
dynamicArray[0] := 1.
dynamicArray[1] := "b".
dynamicArray[2] := 2.3r.
console printLine("static array ",staticArray).
console printLine("dynamic array ",dynamicArray).
].

The output is:

static array 1,2,3
dynamic array 1,b,2.3

== Basic arithmetic operations ==

ELENA supports basic arithmetic operations with integer and floating-point numbers:

import extensions.

program =
[
var n1 := 12.
var n2 := 5.
var n3 := -3.
var r1 := 2.3r.
console printLine(n1, " + ", n2, " = ", n1 + n2).
console printLine(n1, " - ", n2, " = ", n1 - n2).
console printLine(n1, " * ", n3, " = ", n1 * n3).
console printLine(n1, " / ", n2, " = ", n1 / n2).

console printLine(n1, " + ", n2, " * ", r1 ," = ", n1 + n2 * r1).
].

The result is:

12 + 5 = 17
12 - 5 = 7
12 * -3 = -36
12 / 5 = 2
12 + 5 * 2.3 = 23.5

== Conditions, Multi-select, Loops ==

Conditional statement in ELENA are defined as follows:

if(<Boolean expression>)
[ /* doSomething if TRUE*/ ];
[ /*doSomehting if ELSE*/ ].

We could omit else part

if(<Boolean expression>)
[ /*doSomehting if TRUE*/ ].

Usually Boolean expression is a result of a comparison operation:

program =
[
console writeLine("Hello!"); writeLine("How are you?").
var s := console readLine.
if(s == "good")
[ console writeLine("Me too") ];
[ console writeLine("What happends?") ]
].

Several conditions can be checked:

program =
[
console writeLine("Hello!"); writeLine("How are you?").
var s := console readLine.
if((s == "good") || (s == "fine"))
[ console writeLine("Me too") ];
[ console writeLine("What happens?") ]
].

A switch statement can be implemented using => operator:

program =
[
console writeLine("Hello!"); writeLine("How are you?").
var s := console readLine.
s =>
"good" [ console writeLine("Me too") ];
"fine" [ console writeLine("Glad to hear") ];
"bad" [ console writeLine("What's wrong?") ];
"so so" [ console writeLine("It happens") ];
! [ console writeLine("What happens?") ].
].

We could declare *while* loop which will be repeated until the condition is true:

program =
[
console writeLine("Hello!"); writeLine("Guess what?").
var s := console readLine.
while (s != "nothing")
[
console writeLine("Guess what?").
s := console readLine
]
].

Alternatively *until* loop is executed until the condition is met :

program =
[
console writeLine("Hello!"); writeLine("Guess what?").
var s := console readLine.
until (s == "nothing")
[
console writeLine("Guess what?").
s := console readLine
]
].

== Classes, Fields Methods, Constructors ==

Everything in ELENA is a class. So to implement some tasks we will have to declare our own classes.

=== Declaring a simple class ===

Let's create a simple class :

import extensions.
class MyClass
{
// a field
literal myString.
// a constructor
constructor new(literal s)
[
myString := s.
]
// a method
printString
[
console printLine(myString).
]
}
program =
[
// creating a class instance by sending new message to the class
var myClass := MyClass new("This is printed by my class.").
myClass printString.
].
The output will be:

This is printed by my class.

*Note that in ELENA a class is an object itself and can be used by like any other object*

=== Class Inheritance ===

We may inherit our class. When the parent is not explicitly declared - the class inherits *system'Object* super class

import extensions.
class MyParent
{
constructor new
[
console printLine("Parent Constructor.")
]
print
[
console printLine("I'm a Parent Class.")
]
}
class MyChild :: MyParent
{
constructor new
<= new; // calling the parent constructor
[
console printLine("Child Constructor.")
]
print
[
// calling the parent method
$super print.
console printLine("I'm a Child Class.")
]
}
program =
[
var myClass := MyChild new.
myClass print.
].

The output is:

Parent Constructor.
Child Constructor.
I'm a Parent Class.
I'm a Child Class.

=== Private methods ===

It is possible to declare the private methods which cannot be called outside the class.

import extensions.
class MyClass
{
sealed $printPrivate
[
console printLine("private print.")
]
printPublic
[
console print("Calling from public print - ").

// $self is a reference to the current object
$self $printPrivate.
]
}
program =
[
// Note that if the constructor explicitly is not declared
// the system'Object one (without input parameters) is inherited
var myClass := MyClass new.
myClass printPublic.
myClass $printPrivate.
].
The output is:

Calling from public print - private print.
mytest'MyClass : Method mytest#printPrivate not found
Call stack:
system'Exception#class.new$system'LiteralValue[1]:exceptions.l(125)
system'MethodNotFoundException#class.new$system'Object$system'Message[2]:exceptions.l(213)
system'#inline1BF.start[1]:win32_app.l(252)
mytest'program.#invoke[0]:test.l(24)
system'BaseFunction.eval[0]:control.l(172)
system'#inline1BF.start[1]:win32_app.l(37)
system'startUp(5)

=== Properties ===

In normal case the class fields cannot be accessed outside the class. That's why we may declare a special method to access it:

import extensions.
class MyClass
{
int _x.
int x = _x. // get accessor
set x(int o) // set accessor
[
_x := o.
]
}
program =
[
var myClass := MyClass new.
myClass x := 2.
console printLine("MyClass.x=", myClass x).
].
The output is:

MyClass.x=2

We may simplify our code if we will use **prop** attribute:

import extensions.
class MyClass
{
int prop x :: _x.
}
program =
[
var myClass := MyClass new.
myClass x := 2.
console printLine("MyClass.x=", myClass x).
].
== Exception Handling ==

We may use try-catch statement to handle the possible exceptions:

import extensions.
import system'io.
program =
[
try(console printLine(File new("notexistingfile.txt"); content))
{
on(Exception ex)
[
console printLine("Unknown error - ",ex).
]
on(IOException ex)
[
console printLine("I/O error - ",ex).
]
}
].
The output is :

I/O error - Cannot open the file
Call stack:
system'Exception#class.new$system'LiteralValue[1]:exceptions.l(125)
system'io'IOException#class.new$system'LiteralValue[1]:io\ioexceptions.l(10)system'io'FileStream#class.new$system'WideLiteralValue$system'IntNumber$system'IntNumber$system'IntNumber$system'IntNmber[5]:io\win32_files.l(52)
system'io'FileStream#class.openForRead[1]:io\win32_files.l(29)
system'io'StreamReader#class.new[1]:io\win32_files.l(207)
system'io'fileControl.reader[1]:io\win32_files.l(269)
system'io'File.read$system'text'TextBuilder[1]:io\files.l(59)
system'io'File.content[0]:io\files.l(33)
mytest'program.#invoke[0]:test.l(6)
system'BaseFunction.eval[0]:control.l(172)
system'#inline1BF.start[1]:win32_app.l(37)
system'startUp(5)

== See also ==
* ELENA on [https://github.com/ELENA-LANG/elena-lang/ Github]
* ELENA on [https://www.reddit.com/r/elena_lang/ Reddit]
* ELENA on [https://www.reddit.com/r/elena_lang/ Reddit]

Latest revision as of 07:31, 4 September 2019

Language
Elena
This programming language may be used to instruct a computer to perform a task.
Official website
Execution method: Compiled (bytecode)
Garbage collected: Yes
Type safety: Safe
Type strength: Strong
Type expression: Implicit
Type checking: Dynamic
See Also:
Listed below are all of the tasks on Rosetta Code which have been solved using Elena.


ELENA is a general-purpose, object-oriented, polymorphic language with late binding. It features message dispatching/manipulation, dynamic object mutation, a script engine / interpreter and mix-ins.

Subcategories

This category has the following 3 subcategories, out of 3 total.

Pages in category "Elena"

The following 200 pages are in this category, out of 240 total.

(previous page) (next page)
(previous page) (next page)