Skip to content

simonjenga/eo

 
 

Repository files navigation

Donate via Zerocracy

EO principles respected here Managed by Zerocracy DevOps By Rultor.com We recommend IntelliJ IDEA

Build Status PDD status Maintainability Hits-of-Code License

EO (stands for Elegant Objects or ISO 639-1 code of Esperanto) is an object-oriented programming language. It's still a prototype. It's the future of OOP. Please contribute! By the way, we're aware of popular semi-OOP languages and we don't think they are good enough, including Java, Ruby, C++, Smalltalk, Python, PHP, C#: all of them have something we don't tolerate.

EO is not planning to become a mainstream language—this is not what we want. Our main goal is to prove to ourselves that true object-oriented programming is practically possible. Not just in books and abstract examples, but in real code that works. That's why EO is being created—to put all that "crazy" pure object-oriented ideas into practice and see whether they can work. It's an experiment, a prototype, a proof-of-concept.

If you want to contribute, please join our Telegram chat first.

Our Twitter tag is #eolang.

These things we don't tolerate:

  • static/class methods or attributes (why?)
  • classes (why?)
  • implementation inheritance (why?)
  • mutability (why?)
  • NULL (why?)
  • global variables/procedures
  • reflection
  • constants
  • type casting (why?)
  • scalar types
  • garbage collection (huh?)
  • annotations (why?)
  • unchecked exceptions (why?)
  • operators
  • flow control statements (for, while, if, etc)
  • DSL and syntactic sugar (why?)

These things we want to build in:

  • static analysis
  • continuous integration
  • build automation
  • aspects (AOP)
  • logging
  • TDD (discuss)
  • versioning (discuss)
  • concurrency
  • object metadata
  • persistence
  • transactions
  • licensing
  • artifact repositories

These things we are not sure about (please, help us):

We want EO to be compilable to Java. We want to stay as close to Java and JVM as possible, mostly in order to re-use the eco-system and libraries already available.

We also want to have an ability to compile it to any other language, like Python, C/C++, Ruby, C#, etc. In other words, EO must be platform independent.

Quick Start

Here is a classic "hello, world" example:

import org.eolang.cli
import org.eolang.printed
import org.eolang.string
cli:
  printed:
    string:
      "Hello, world!"

This code will compile into a .java class that will compile into a .class byte code that will run and print "Hello, world!".

What exactly happens here? TBD

Details

There are types, objects, constructors, destructors, methods, attributes, parameters, exceptions, decorators.

There are no classes, variables, operators, statements, annotations, reflection, type casting, generics, NULL, static methods, functions, lambdas.

Types

A type is a contract an object must obey.

A type is very similar to interfaces from Java 1.0. A type has a name and a list of method declarations. Each method declaration has a name of the type of the return value, a method name, and a list of parameters. Each method declaration has to take exactly one line, without any terminating symbol at the end, for example:

type Book:
  Text asText()
type Car:
  Money cost()
  Bytes picture()
  Car moveTo(Coordinates coords)
type Pixel extends Point:
  Pixel moveTo(Int x, Int y)
  Bytes drawTo(Canvas canvas)

There is only one built-in type Bytes, which is very similar to byte[] in Java.

A type may become a subtype of another type by using keyword extends.

A type may have one to four method declarations.

The type name must match [A-Z][A-Za-z0-9]{2,15}.

Objects

An object is an active entity that implements one or more types.

An object can be created or copied. When an object is created all methods required by its types must be implemented, for example (alphabet is the name of the object):

object alphabet as Book:
  Text @isbn
  Text @title
  ctor()
    alphabet:
      "978-1-51916-691-3",
      "The Alphabet"
  ctor(String i, String t):
    @isbn = i
    @title = t
  Text asText():
    sprintf:
      "ISBN is %s, title is '%s'",
      @isbn,
      @title

An object can be made as a copy of an existing object, but with a different (or similar) set of parameters for one of the constructors, for example (ot is the name of the object):

ot: "978-0-73561-965-4", "Object Thinking"

The same can be written in a few lines (comma at the end is mandatory):

ot:
  "978-0-73561-965-4",
  "Object Thinking"

Object creating and copying may be combined in any possible way, for example:

Ticket ticket(Person passenger):
  object as Ticket:
    Person @p
    ctor(Passenger p)
    Text name():
      concat:
        "506-",
        @p.name()
    Money price():
      if:
        @p.vip(),
        money("$50"),
        object () as Money
          Int value():
            25

The object name must match [a-z][a-z0-9]{2,15}.

Attributes

An attribute is the coordinate of an encapsulated object.

An object may have a number of attributes, listed right after the first line of object declaration:

object zero(0, "USD") as Money:
  Int @amount
  Text @currency

All attributes are private; there is no such thing as public or protected attributes.

An object may have up to five attributes.

The attribute name must match @[a-z][a-z0-9]{2,15}.

Constructors and Destructors

A constructor is a ... TBD

A destructor is a ... TBD

An object has a primary constructor by default, it saves parameters into attributes. So object must have at least one attribute, i.e. the object must encapsulate something. Parameters order is same as order of attributes. Object may have any number of secondary constructors and one destructor. A primary constructor is the one that initializes object attributes and can't have a body, for example:

object zero() as Money, Int:
  Int @amount
  Text @currency
  ctor(): # secondary constructor
    zero: 0
  ctor(Int a): # secondary constructor
    zero: a, "USD"
  dtor(): # destructor
    printed: "I'm dying..."

Obviously, parameter names in the primary constructor must match the names of object attributes.

Secondary constructors must return objects that implement at least all types mentioned in the declaration of the current object.

The destructor, if it is present in the object, will be called right before the object is destroyed. The object returned by the destructor is activated immediately after being returned.

Constructors must be listed after attributes. The primary constructor must be the last one. The destructor, if it is present, goes right after the primary constructor.

For constructors the ctor keyword is used and for destructors, the keyword is dtor.

Methods

A method is a behavior exposing instrument of an object.

Method body must create and return exactly one object, using a single "statement", for example:

Int max(Int a, Int b):
  if:
    firstIsLess:
      a,
      b
    b,
    a

A method must return something; there is no such thing as void like there is in Java/C++.

A method may not exist in an object if it is not defined in one of its types.

All methods are public; there is no such thing as private or protected methods.

A method may have zero to four parameters.

Each parameter must have an optional type and a name. If type is not provided it has to be replaced with ? mark, for example:

Int power(? x, Int p):
  if:
    equals: p, 0,
    1,
    mul:
      x,
      power: x, minus: p, 1

This code will lead to compile-time error if x doesn't implement Int.

The method name must match [a-z][a-z0-9]{2,15}.

A single empty line is allowed after the method body, nowhere else.

Decorators

A decorator is an object that encapsulates another object, implements the same set of methods, and passes all method calls to the encapsulated object.

A decorator is created using keyword decorates, for example:

object zero as Money, Int:
  # ...
object one decorates zero:
  # ...

Encapsulated object can be accessed through keyword origin, for example:

object one decorates zero:
  Text print:
    origin.asText() # here

A decorator has a single-argument primary constructor, which accepts what will be encapsulated as origin, for example:

object one decorates zero:
  ctor()  # secondary ctor
    one: 1
  ctor(num)  # secondary ctor
    one: # call one-arg primary ctor
      zero:
        num
  Text print:
    origin.asText()

Exceptions

To raise an exception object org.eolang.error must be copied (imported by default):

import org.eolang.error # you can omit this line
Int price(Int total, Int amount):
  if:
    equals: amount, 0
    error: "Division by zero"
    div: total, amount

To catch an exception... TBD

Popular Types and Objects

Some types are the most popular:

Int
Boolean
Double
String

Some objects are popular as well:

if
equals as Boolean
not as Boolean
firstIsLess as Boolean
firstIsGreater as Boolean
plus
minus
mul
div

Examples

A Fibonacci number:

object fibonacci(1) as Int:
  Int @n
  ctor():
    fibonacci: 1
  Int int():
    if:
      firstIsLess: @n, 2
      1,
      plus:
        @n
        fibonacci:
          minus: @n, 1

Here, if, firstIsLess, plus, and minus are objects being copied.

How to contribute

Fork repository, make changes, send us a pull request. We will review your changes and apply them to the master branch shortly, provided they don't violate our quality standards. To avoid frustration, before sending us your pull request please run full Maven build:

$ mvn clean install -Pqulice

Troubleshooting

If after clean import from Maven, IDEA doesn't compile the project and shows errors about ProgramLexer is undefined:

  • Open Maven Projects window
  • Select eo-compiler
  • Right button
  • Generate Sources and Update Folders

About

EO programming language

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 94.2%
  • ANTLR 5.1%
  • Groovy 0.7%