Category:Elena

From Rosetta Code
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.

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

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)