Category:Elena: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 262: Line 262:
import extensions.
import extensions.
program =
public program =
[
[
var staticArray := (1,2,3).
var staticArray := (1,2,3).

Revision as of 08:56, 14 June 2018

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:

   public 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).

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

   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

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:

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

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

   T<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 := T<literal>(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 := T<literal>(2) 

It is guaranteed that the result of the cast message is an instance of LiteralValue, so if the object supports the message the conversion will be done quietly.

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.
   
   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

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 rogram =
   [
       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.
   
   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$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.
   
   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 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.
   
   public 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
   {
       private 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)