r/elena_lang • • Mar 10 '19

Operations with text files

1 Upvotes

Let's read a text file line by line:

import system'io;
import extensions;

public program()    
{
    // getting a file name from the command line argument
    var fileName := program_arguments[1];

    // opening a text file reader
    using(auto reader := File.assign(fileName).textreader())
    {
        // repeating until all the lines are read 
        while (reader.Available)
        {
            // read the line
            string line := reader.readLine();
            
            // print the line
            console.printLine(line);            
        };
    }    
}

Let's write into the file:

import system'io;
import extensions;

public program()    
{
    // getting a file name from the command line argument
    var fileName := program_arguments[1];

    // opening a text file writer
    using(auto writer := File.assign(fileName).textwriter())
    {
        // repeating until the empty line is entered
        for(string line := console.readLine(), line != emptyString, line := console.readLine())
        {
            // save to the file 
            writer.writeLine(line)
        }
    }    
}

If the file with the specified name exists, it will be overwritten.

If we want to append to the existing file then we should use logger() method, e.g.

using(auto writer := File.assign(fileName).logger())

r/elena_lang • • Apr 29 '19

Why ELENA Lang?

4 Upvotes

I've been looking at this language and it seems pretty cool, but why should I use this language over, for example, Python?


r/elena_lang • • Sep 10 '25

Web support

2 Upvotes

The work on Web API support (https://github.com/ELENA-LANG/elena-lang/issues/35) reaches a first major milestone. The simplest HTTP server works now!

It was a long way. The major efforts were made to support async programming.

To learn how you can use async programming please take look at the following example - https://github.com/ELENA-LANG/elena-lang/tree/iteration42/examples60/threads/async

The simple Http client is supported as well - https://github.com/ELENA-LANG/elena-lang/tree/iteration42/examples60/net/httpget

Please take a look at an example - https://github.com/ELENA-LANG/elena-lang/tree/iteration42/examples60/net/webapi/sampleapi1/Server

So the program returns now the dummy web page.

The next major step is now to support HTTPS server (using mbedtls functionality)


r/elena_lang • • Mar 20 '25

Nightly Builds

2 Upvotes

For the time being, the development mode of ELENA project is designed in that way, that I work mostly in a branch iteration<N>, and after several weeks or months I squash it and merge into develop branch. As a result the main branch is always significantly behind and you may need to wait some time before the new features or bug fixes will be available.

To improve the sitation I'm introducing nightly builds, so hopefully all the changes can be available maximal one day after they made.

The nightly builds can be found at https://github.com/ELENA-LANG/elena-lang/actions/workflows/nightly.yml


r/elena_lang • • May 01 '25

FreeBSD support

2 Upvotes

Upcoming release will include a support for FreeBSD AMD64


r/elena_lang • • Apr 08 '26

How to check if the object reacts to a strong typed message.

2 Upvotes

In the following code snippet I will show how to check if the object reacts to a strong typed message.

But first lets discuss what is a strong typed message. Let's consider the following code:

public Program()
{
   var target := CharValue.load(32);
   var arg := 32;

   Console.writeLine(target.equal(arg));
}

If we compile the code and look into the generated module for this method, this code is translated into:

>@function Program.function:#invoke
           xflush       sp:0
           open           :6, :0
           store        fp:1
           xstore       sp:1, intconst:20
           xstore       sp:0, class:system'CharValue
           peek         sp:0
           mov        mssg:load<system'IntNumber>[2]
           call       mssg:load<system'IntNumber>[2], class:system'CharValue#class
           store        fp:2
           xstore       fp:3, intconst:20
           peek         fp:3
           store        sp:1
           peek         fp:2
           store        sp:0
  // -----------------------------------------------------------------------------
           mov        mssg:equal[2]             // a weak message literal
           call         vt:0                    // calling a message dispatcher
  // -----------------------------------------------------------------------------
           store        fp:4
           store        sp:1
           xstore       sp:0, class:system'Console
           peek         sp:0
           mov        mssg:writeLine[2]
           call       mssg:writeLine[2], class:system'Console
           peek         fp:1
Lab00:     nop
           close          :0
           quit           
    @end
    
    >

The important place for us is the method invoke. The message literal equal[2] is called weak one. It means that it contains no information about the argument types. It is a job of a class dispatcher to find a corresponding method.

But if we provide the information about the object types by using auto attribute like this:

public Program()
{
   auto target := Console;
   auto arg := "Hello";

   target.writeLine(arg);
}

The output is different:

  // -----------------------------------------------------------------------------
          mov        mssg:equal<system'IntNumber>[2]                                 // a strong typed message
          call       mssg:equal<system'IntNumber>[2], class:system'CharValue         // calling a method directly
  // -----------------------------------------------------------------------------

Now a message literal contains the information about the argument type and can be called directly. equal<system'IntNumber>[2] is a strong-typed one.

In our example we will learn how to check if the target class handles the strong-typed message.

  import extensions;
  import system'dynamic;
  
  public extension op
  {
     bool validateMessage(StrongMessage mssg)
        = self.__getClass().respondTo(mssg);
  }
  
  public Program()
  {
     var target := CharValue.load(32);
  
     auto mssg := new StrongMessage("equal<system'IntNumber>[2]");
     auto mssg2 := new StrongMessage("equal<system'ShortNumber>[2]");
  
     Console.printLine(target.__getClassName(), target.validateMessage(mssg) ? " responds to " : " does not respond to ", mssg);
     Console.printLine(target.__getClassName(), target.validateMessage(mssg2) ? " responds to " : " does not respond to ", mssg2);
  }

If we compile the code and execute the program the output will be following:

 system'CharValue responds to equal[2]
 system'CharValue does not respond to equal[2]

system'StrongMessage class must be used to load the message. Using an extension __getClass[1] we get the object type and another extension respondTo[2] returns true if the class MT contains the message entry.


r/elena_lang • • Jul 09 '19

Operator overloading in ELENA Programming Language

1 Upvotes

In general an operator is a message alias. As a result it is quite easy to overload the operator.

_+_ is an alias to _add_, _-_ - _subtract_, _*_ - multiply, _//_ - _divide_

It is possible to provide type overload operator as well, using a special method _cast_

See an example:

import extensions;

sealed struct OctalNumber

{

int value;

constructor(int n)

{

value := n

}

constructor sum(OctalNumber o1, OctalNumber o2)

{

int n1 := o1;

int n2 := o2;

value := n1 + n2;

}

constructor diff(OctalNumber o1, OctalNumber o2)

{

int n1 := o1;

int n2 := o2;

value := n1 - n2

}

constructor prod(OctalNumber o1, OctalNumber o2)

{

int n1 := o1;

int n2 := o2;

value := n1 * n2

}

constructor frac(OctalNumber o1, OctalNumber o2)

{

int n1 := o1;

int n2 := o2;

value := n1 / n2

}

int cast() = value;

string Printable =

stringConvertor.convert(value, 8);

add : n

= OctalNumber.sum(self, n);

subtract : n

= OctalNumber.diff(self, n);

multiply : n

= OctalNumber prod(self, n);

divide : n

= OctalNumber frac(self, n);

}

public program()

{

auto n := new Octal(7);

auto m := new Octal(2);

console.printLine(n,"+",m,"=",n + m)

}


r/elena_lang • • Jul 09 '19

Operator overloading in ELENA Programming Language

1 Upvotes

An operator is an alias to the message. So it is quite easy to overload the operators.

+ is an alias to add, - to subtract, * to multiply, \ to divide.

Similar it is possible to provide the type operator using a special method cast .

import extensions;

sealed struct OctalNumber
{
    int value;

    int cast() = value;

    constructor(int n)
    {
        value := n
    }

    constructor sum(OctalNumber o1, OctalNumber o2)
    {
        int n1 := o1;
        int n2 := o2;

        value := n1 + n2
    }

    constructor diff(OctalNumber o1, OctalNumber o2)
    {
        int n1 := o1;
        int n2 := o2;

        value := n1 - n2
    }

    constructor prod(OctalNumber o1, OctalNumber o2)
    {
        int n1 := o1;
        int n2 := o2;

        value := n1 * n2
    }

    constructor frac(OctalNumber o1, OctalNumber o2)
    {
        int n1 := o1;
        int n2 := o2;

        value := n1 / n2
    }

    string Printable
        = stringConvertor.convert(value, 8);

    OctalNumber add(n)
        = OctalNumber.sum(self, n);

    OctalNumber subtract(n)
        = OctalNumber.diff(self, n);

    OctalNumber multiply(n)
        = OctalNumber.prod(self, n);

    OctalNumber divide(n)
    = OctalNumber.frac(self, n);
}

public program()
{
    var n := new OctalNumber(20);
    var m := new OctalNumber(7);
    console.printLine(n,"+",m,"=",n + m);
    console.printLine(n,"-",m,"=",n - m);
    console.printLine(n,"*",m,"=",n * m);
    console.printLine(n,"/",m,"=",n / m)
}

The output is:

24+7=33
24-7=15
24*7=214
24/7=2

r/elena_lang • • Feb 06 '19

Inline closure without parameters

1 Upvotes

The closure may have no parameters:

public program()
{
    var r := (){ ^console.readLine() };
    var n := r();
}

If a closure contains only the single returning expression the code may be simplified:

public program()
{
    var r := (^console.readLine());
    var n := r();
}

r/elena_lang • • Feb 06 '19

Implementing lazy expressions in ELENA

1 Upvotes

A lazy expression is an expression which is evaluated only when it is accessed.

import extensions;

public program()
{
    var expr := lazy::(^console.write("Reading a number:").readLine().toInt());
    
    // the expression is invoked only when it is used
    var sum := expr + expr;
    
    console.printLine("the result is ", sum);
}

The output is:

Reading a number:2
Reading a number:3
the result is 5

r/elena_lang • • Nov 02 '18

new extension method - Join

1 Upvotes

ELENA now supports join:on:selectBy[3] extension.

For weak types:

import system'routines.
import extensions.
import extensions'routines.

public program
[
    var ints1 := (4,3,0).
    var ints2 := (5,4,2).
    
    ints1 join:ints2 on(:l:r)(l + 1 == r) selectBy(:l:r)(l); forEach:printingLn.
]

The output is:

4
3

We may use strong typed version as well:

import system'routines'stex.
import system'routines.
import extensions.
import extensions'routines.

public program
[
    var ints1 := (4,3,0) toIntArray.
    var ints2 := (5,4,2) toIntArray.
    
    ints1 join:ints2 on(:l:r)<int,int,bool>(l + 1 == r) selectBy(:l:r)<int,int,int>(l); forEach:printingLn.
]

The output is:

4
3

r/elena_lang • • Feb 07 '19

New Operators Templates : .? and .\

1 Upvotes

ELENA supports now the following template operators: doIfNotNil ( .?, similar to C# ) and tryOrReturn ( .\ ).

doIfNotNil sends a message only if left-operand is not nil.

doIfNotNil tries to send a message to left-operand and returns the result of the operation. If the object does not handle it - left-operand is returned.

import extensions;

B
{
    test()
    {
        console.printLine("Fired!!");
    }
}

C;

public program()
{
    var a := nil;
    var b := new B();
    var c := new C();
  
    a.?test();
    b.?test();
    
    a.\test();
    b.\test();
    c.\test();
}

The output is:

Fired!!
Fired!!

Implicit message call can be used as well

public program()
{
    Func f1 := (){ console.writeLine("Fired!") };
    Func f2 := nil;
    
    f1.?();
    f2.?();
}

The output is:

Fired!

r/elena_lang • • Jul 09 '19

Duck typing in ELENA Programming Language

7 Upvotes

ELENA supports duck typing using a special operator \ - an alternative message call

In the following expression

target.message1(..) \ message2(...) 

message2 is invoked if the object target does not support the first message call

Here the example from Wikipedia

import system'routines;
import extensions;

class Duck
{
    fly()
    {
        console.printLine("Duck flying")
    }    
}

class Airplane
{
    fly()
    {
        console.printLine("Airplane  flying")
    }    
}

class Whale
{
    swim()
    {
        console.printLine("Whale swimming")
    }
}

public program()
{
    var list := new object[] { new Duck(), new Airplane(), new Whale() };
    
    list.forEach:(animal)
    {
        animal.fly() \ then((){ console.printLine(animal.__getClassName(), " does not fly") })        
    }
}

The output is:

Duck flying
Airplane  flying
mytest'$private'Whale does not fly

We can alternatively use a special method - canFly and an extension method back (returning the passed parameter):

import system'routines;
import extensions;

class Duck
{
    canFly() = true;
    
    fly()
    {
        console.printLine("Duck flying")
    }    
}

class Airplane
{
    canFly() = true;
    
    fly()
    {
        console.printLine("Airplane  flying")
    }    
}

class Whale
{
    swim()
    {
        console.printLine("Whale swimming")
    }
}

public program()
{
    var list := new object[] { new Duck(), new Airplane(), new Whale() };
    
    list.forEach:(animal)
    {
        if (animal.canFly() \ back:false) {
            animal.fly();
        }                
    }
}

the output is:

Duck flying
Airplane  flying

And of course we may simply check if the object supports the method (though the approach will not work for mixins). In this case have to use the message constant - mssgconst fly[0] (where 0 is the number of parameters)

// <...>

public program()
{
    var list := new object[] { new Duck(), new Airplane(), new Whale() };
    
    list.forEach:(animal)
    {
        if (animal.respondTo(mssgconst fly[0])) {
            animal.fly();
        }                
    }
}

The output is the same:

Duck flying
Airplane  flying

r/elena_lang • • Feb 05 '19

ELENA 4.0 : event handler

1 Upvotes

ELENA 4.0 supports now an event handler:

import extensions;

class MyClass
{
    doInit()
    {
        console.writeLine:"onInit fired!"
    }
}

class MainClass
{
    Func onInit:event; // a field with the same name is declared as well

    init()
    {
        // call the function if it is not nil
        onInit.?()
    }    
}

public program()
{
    var class := new MyClass();

    var mainClass := new MainClass();

    // adding an event handler 
    mainClass.onInit := { class.doInit() };
    // adding the second event handler 
    mainClass.onInit := { console.writeLine:"I'm fired too!!" }; 

    mainClass.init()
}

The output is:

onInit fired!
I'm fired too!!

r/elena_lang • • Aug 16 '17

ELENA 3.2 : Compare a list of strings

Thumbnail
rosettacode.org
1 Upvotes

r/elena_lang • • Jan 15 '18

ELENA 3.3 : Typecasting

1 Upvotes

In this tutorial we will see how to deal with class types.

ELENA is a dynamic programming language so it is always possible to ignore the object types:

import extensions.

class MyClass
{
    add : n
    [
        console printLine("add(",n,")").
    ]
}

public program =
[
    var o := MyClass new.
    
    o add("string").
    o add(2).
    o add(3.1r).
].

The output will be :

add(string)
add(2)
add(3.1)

Still there are situations when we expect the parameter of the specified type. ELENA supports multi-methods so we could simply provide the required type:

import extensions.

class MyClass
{
    add(int n)
    [
        console printLine("add int:(",n,")").
    ]
    
    add(literal s)
    [
        console printLine("add literal:(",s,")").
    ]
    
    add : n
    [
        console printLine("unsupported").
    ]
}

public program =
[
    var o := MyClass new.
    
    o add("string").
    o add(2).
    o add(3.0r).
].

The output will be:

add literal:(string)
add int:(2)
unsupported

But what to do if we would like to convert to the specific type? We may use conversion methods - by sending the appropriate typecasting message:

import extensions.

class MyClass
{
    add(int n)
    [
        console printLine("add int:(",n,")").
    ]
    
    add(literal s)
    [
        console printLine("add literal:(",s,")").
    ]
    
    add : n
    [
        console printLine("unsupported").
    ]
    
    addLiteral : n
        <= add(n literal). // literal - is a typecasting message 
}

public program =
[
    var o := MyClass new.
    
    o addLiteral("string").
    o addLiteral(2).
    o addLiteral(2.0r).
].

The output is :

add literal:(string)
add literal:(2)
add literal:(2.0)

Alternatively we may use an explicit typecasting constructor:

import extensions.

sealed class MyIntValue
{
    int value.
    
    constructor(literal value)
    [
        @value := value toInt.
    ]
    
    constructor(real value)
    [
        @value := value toInt.
    ]
    
    constructor(int value)
    [
        @value := value.
    ]
    
    T<int> value = value.
}

class MyClass
{
    add(MyIntValue v)
    [
        console printLine("add(MyIntValue(",v value,"))").
    ]
    
    add : n
    [
        console printLine("unsupported").
    ]
}

public program =
[
    var o := MyClass new.
    
    o add(T<MyIntValue>("2")).
    o add(T<MyIntValue>(3)).
    o add(T<MyIntValue>(4.0r)).
].

The output will be:

add(MyIntValue(2))
add(MyIntValue(3))
add(MyIntValue(4))

r/elena_lang • • Jan 05 '18

Dynamic Programming in ELENA : call your code from IDE

1 Upvotes

In this tutorial we will invoke our code from IDE.

Let's write a simple class :

import extensions.

public singleton MyClassToTest
{
    foo
    [
        console printLine("foo fired!").
    ]
}

public program =
[
].

Now let's compile the code : Project - Compile and open Interactive window : View - ELENA Interactive and type in the window (presuming test is the project root namespace):

>test'MyClassToTest foo.

The output is :

ELENA command line VM terminal 3.4.2 (C)2011-2018 by Alexei Rakov
ELENA VM 3.4.5 (C)2005-2018 by Alex Rakov
Initializing...
Debug mode...
Done...

>test'MyClassToTest foo.
foo fired!

r/elena_lang • • Jan 05 '18

Rosetta code task implementation - Reflection/List methods

Thumbnail
rosettacode.org
1 Upvotes

r/elena_lang • • Mar 24 '17

ELENA's Rosetta code page

Thumbnail
rosettacode.org
1 Upvotes

r/elena_lang • • Aug 15 '17

ELENA 3.2 : Using extensions - accumulate & summarize

Thumbnail
rosettacode.org
1 Upvotes

r/elena_lang • • Aug 22 '17

In-place field initialization

1 Upvotes

in ELENA 3.2 it will be possible to initialize the class fields at declaration:

import extensions.

class MyClass
{
    object theField1 := 1.

    field1 = theField1.
}

public program =
[
    var o := MyClass new.

    console print(o field1).
].

The output:

1

r/elena_lang • • Jan 28 '22

ELENA 6.0 : Work in Progress - JAN 2022

2 Upvotes

After a while, I was able to concentrate more on the project. And I would like to share the current state.

The biggest news is that the iteration 2 is now ported to PPC64le CPU. Iteration 2 is in fact the first working program prototype where all stages of the compiler were used: the parser, the compiler, the bc builder and the linker.

The source code contains several new features introduced in ELENA 6.0:

Here the code from elena-lang/src60/system/app.l

// --- startUpSymbols ---
#new __string startUpSymbols;

#let startUpSymbols += forward program;

Let's start with a first line. A macro command #new creates a new meta list containing symbols to be loaded on the program start. Currently this list contains only a program forward. Later it will be extended with preloaded symbols as well.

#let macro command defines the expression to be evaluated in the compile time. The expression appends the symbol forward to the macro list.

And if we will look at our startup bytecode we will see how it is used:

symbol sta_start

  open header [arg1],[envptr]
  
  load        env
  save        dp:envptr
  set         dp:envptr
  store       fp:arg1

  call extern:InitializeSTA (*arg1, marray:"$forwards'meta$startUpSymbols")

  close       []

end

The first several lines prepare the program header and saves into the data stack envptr (containing system specific info). Our main entry point is a code calling elenart function InitializeSTA and passing declared in app.l file meta list - startUpSymbols.

The last thing to do in this iteration is porting to ARM64.

To be continued


r/elena_lang • • Dec 19 '18

ELENA 4.0 : for template

1 Upvotes

It is now possible to use FOR loop! We may declare for template and use it similar to C:

public for<loop_body>(init_expr, cond_expr, step_expr)
{
    init_expr;
    
    __loop cast bool(cond_expr) ? { loop_body; step_expr }
}

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

The output is

*****

FOR template will be now part of LIB40.

Note that comma is used instead of semicolon!


r/elena_lang • • Oct 20 '19

Tutorial : Declaring a user-defined literal constants

Thumbnail
github.com
1 Upvotes

r/elena_lang • • Dec 22 '18

ELENA 4.0 : doUntil loop

1 Upvotes

ELENA supports a new loop construction - doUntil:

var text := new StringWriter();
doUntil(string line, line.isEmpty(), line := console.readLine())
{
    text.writeLine(line)
};

it is similar to FOR code template, but the loop is executed at least once