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.
Your Help Needed
If you know Elena, please write code for some of the tasks not implemented in 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[edit]

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

   public program()
   {
   }

Everything in ELENA is an object. To interact with it we have to send a message. The message consists of *an action* and a *parameter list*.

The statement should be terminated by a semicolon.

   public program()
   {
       console.writeLine("Hello!");
   }

In our example the action is **writeLine** and the parameter list consists of a single string 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:

   public 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:

   public 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[edit]

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 string constant value.

The assigning value can be an expression itself:

   public program()
   {
       console.writeLine("Hello!").writeLine("How are you?");
       var s := console.readLine()
   }

ELENA is a dynamic language and in most cases we may not specify the variable type:

   public program()
   {
       var s := "Hello";
       console.writeLine(s);
       s := 2;
       console.writeLine(s);
   }

The output will be:

   Hello
   2

But it is possible to specify the variable expected type:

   String s := "Hello";
   console.writeLine(s);
  • where system'String is a class representing text as a sequence of UTF-8 characters.*

We may use a class alias to simplify the code:

   string s := "Hello";  // string is a String class alias
   console.writeLine(s);

ELENA does not enforce types in compilation-time, so the following code will be successfully compiled:

   string s := "Hello";
   s := 2;

But it will raise an exception in the run-time:

   system'IntNumber : Method #cast[0] not found
   Call stack:
   system'Exception#class.new[1]:exceptions.l(125)
   system'MethodNotFoundException#class.new[2]:exceptions.l(236)
   system'$inlineC.start[0]:win32_app.l(313)
   mytest'program.#invoke[0]:test.l(5)
   system'$inlineC.start[0]:win32_app.l(39)
   system'#startUp:win32_app.l(52)

As you may see, the compiler injects the typecasting code, so the actual code looks like this:

   string s := "Hello";
   s := cast string(2);
  • where* **cast string(2)** *is a construction to typecast the target expression* - **a numeric constant** - *to the expected type* - **System'String**

As a result if the object supports casting method the operation will work. For example, system'IntNumber can be implicitly converted into system'RealNumber so the following code:

   public program()
   {
       real r := 2;
       console.writeLine(r)
   }
  

will be successfully executed with the result:

   2.0

Basic Types[edit]

The Boolean Type[edit]

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

   import extensions;
   
   public 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[edit]

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;
   
   public 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[edit]

    • String** is used to store the text encoded in UTF-8. String is a 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;
   
   public 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;
   public 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[1]:exceptions.l(125)
   system'OutOfRangeException#class.new[1]:exceptions.l(156)
   system'OutOfRangeException#class.new[0]:exceptions.l(156)
   system'String.at[1]:memory.l(1243)
   mytest'program.#invoke[0]:test.l(8)
   system'$inlineC.start[0]:win32_app.l(39)
   system'#startUp:win32_app.l(52)

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

   import extensions;
   
   public 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;
   
   public program()
   {
       var s := "Привет";
       
       console.printLine("The first character of ",s," is ", s.FirstMember);
       console.printLine("The last character of ",s," is ", s.LastMember)
   }

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

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

Array types[edit]

It is possible to declare a generic (_system'Array_) or strong-typed template-based (_system'Array#1_) array.

   import extensions;
   
   public program()
   {
       var strongTypedArray := new int[] {1,2,3};
       
       var genericArray := Array.allocate(3);
       genericArray[0] := 1;
       genericArray[1] := "b";
       genericArray[2] := 2.3r;
   
       console.printLine("strong-typed array ",strongTypedArray.asEnumerable());
       console.printLine("dynamic-typed array ",genericArray.asEnumerable());
   }

The output is:

   strong-typed array 1,2,3
   dynamic-typed array 1,b,2.3

Basic arithmetic operations[edit]

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

   import extensions;
   
   public 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

?? operator[edit]

Operator ?? is used to deal with nil.

_a ?? b_ - will return _a_ if _a_ is not _nil_ or _b_

See the following code:

   import extensions;
   
   public program()
   {
       var a := nil;
       var b := a ?? 0 + 2;
       console.printLine(a ?? "nil", " ?? 0 + 2 = ", b);
               
       a := 1;
       b := a ?? 0 + 2;
       console.printLine(a ?? "nil", " ?? 0 + 2 = ", b);
   }

The output is:

   nil ?? 0 + 2 = 2
   1 ?? 0 + 2 = 3

The operator can be used for typecasting operations as well:

_cast type(a) ?? b_ - will typecast _a_ to _type_ or return _b_ if it is not possible.

See the code:

   import extensions;
   
   public program()
   {
       string s := "a";
       var n := 2;
       
       console.printLine("cast int(",s,") ?? 0 = ", cast int(s) ?? 0);
       console.printLine("cast int(",n,") ?? 0 = ", cast int(n) ?? 0);
   }

The output is:

   cast int(a) ?? 0 = 0
   cast int(2) ?? 0 = 2

Conditions, Multi-select, Loops[edit]

Conditional statement in ELENA are defined as follows:

   if(<Boolean expression>)
   { 
      /* doSomething if TRUE*/ 
   }
   else
   {
      /*doSomehting if ELSE*/
   };

We could omit else part

   if(<Boolean expression>)
      { /*doSomehting if TRUE*/ };

Usually Boolean expression is a result of a comparison operation:

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

Several conditions can be checked:

   public program()
   {
       console.writeLine("Hello!").writeLine("How are you?");
       var s := console.readLine();
       if((s == "good") || (s == "fine"))
       { 
           console.writeLine("Me too") 
       }
       else
       {
           console.writeLine("What happends?")
       }
   }

A switch statement can be implemented using => operator:

   public 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:

   public 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 :

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

ELENA supports C-styled *for* loop as well:

   public program()
   {
       for(int n := 0, n < 5, n += 1)
       {
           console.write("*")
       }            
   }

The output is:

   *****

_Note that comma is used instead of semicolon!_

  • doUntil* loop is similar to *for*, but the loop is executed at least once:
   var text := new StringWriter();
   doUntil(string line, line.isEmpty(), line := console.readLine())
   {
       text.writeLine(line)
   };

Classes, Fields Methods, Constructors[edit]

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

Declaring a simple class[edit]

Let's create a simple class :

   import extensions;
   
   class MyClass
   {
       // a field
       string myString;
   
       // an implicit constructor
       constructor(string s)
       {
           myString := s
       }
       
       // an explicit constructor
       constructor fromNuber(int n)
       {
           myString := n.toString();
       }
       
       // a method
       printString()
       {
           console.printLine(myString)
       }
   }
   
   public program()
   {
       // creating a class instance by sending new message to the class
       var myClass := new MyClass("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[edit]

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.")
       }
   
       printMe()
       {
           console.printLine("I'm a Parent Class.")
       }    
   }
   
   class MyChild : MyParent
   {
       
       constructor new()
           <= new() // calling the parent constructor
       {
           console.printLine("Child Constructor.")
       }
       
       printMe()
       {
           // calling the parent method
           super.printMe();
           
           console.printLine("I'm a Child Class.")
       }
   }
   
   public program()
   {
       var myClass := MyChild.new();
       
       myClass.printMe()
   }

The output is:

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

Private methods[edit]

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

   import extensions;
   
   class MyClass
   {
       private printPrivate()
       {
           console.printLine("private print.")
       }
       
       printPublic()
       {
           console.print("Calling from public print - ");
   
           // self is a reference to the current object
           self.printPrivate()
       }
   }
   
   public program()
   {
       // Note that if the constructor explicitly is not declared 
       // the system'Object one (without input parameters) is inherited
       var myClass := new MyClass();
       
       myClass.printPublic();
       myClass.printPrivate()
   }

The output is:
   Calling from public print - private print.
   mytest'$private'MyClass : Method printPrivate[0] not found
   Call stack:
   system'Exception#class.new[1]:exceptions.l(125)
   system'MethodNotFoundException#class.new[2]:exceptions.l(236)
   system'$inline16.start[0]:win32_app.l(313)
   mytest'program.#invoke[0]:test.l(26)
   system'$inline16.start[0]:win32_app.l(39)
   system'#startUp:win32_app.l(52)

Properties[edit]

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

   import extensions;
   class MyClass
   {
       int _x;
   
       get int x() = _x;  // get accessor
   
       set x(int o)       // set accessor 
       {
          _x := o
       }
   }
   
   public program()
   {
       var myClass := new MyClass();
   
       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** field template:

   import extensions;
   
   class MyClass
   {
       int _x;
       
       prop int x
       {
           get() = _x;
           
           set(int val)
           {
               _x := val;
           }
       }
   }
   
   public program()
   {
       var myClass := new MyClass();
   
       myClass.x := 2;
   
       console.printLine("MyClass.x=", myClass.x)
   } 

Simple accessors can be omitted:

   import extensions;
   
   class MyClass
   {
       prop int x;
   }
   
   public program()
   {
       var myClass := new MyClass();
   
       myClass.x := 2;
   
       console.printLine("MyClass.x=", myClass.x)
   }

Exception Handling[edit]

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

   import extensions;
   
   public program()
   {
       try
       {
           new Object().nonExistingMethod();
       }
       catch(MethodNotFoundException e)
       {
           console.printLine("Method not found")
       }
       catch(Exception e)
       {
           console.printLine("Unknown error")
       }
   }

The output is :

   Method not found

See also[edit]

Subcategories

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

Pages in category "Elena"

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