Blog tagged progress

When ceylon.test met meta-model

Ceylon has had support for unit testing since milestone four, but its functionality was pretty limited due lack of annotations and meta-model at that time.

Fortunately this is not true anymore! With version 1.0 of Ceylon we also released a completely rewritten ceylon.test module. So let’s see what’s new and how we can use it now.

Tests annotations

Tests are now declaratively marked with the test annotation and can be written as top-level functions or methods inside top-level class, in case you want to group multiple tests together.

Inside tests, assertions can be evaluated by using the language’s assert statement or with the various assert... functions, for example assertEquals, assertThatException etc.

class YodaTest() {

    test
    void shouldBeJedi() {
        assert(yoda is Jedi, 
               yoda.midichloriansCount > 1k);
    }

    ...
}

Common initialization logic, which is shared by several tests, can be placed into functions or methods and marked with the beforeTest or afterTest annotations. The test framework will invoke them automatically before or after each test in its scope. So top-level initialization functions will be invoked for each test in the same package, while initialization methods will be invoked for each test in the same class.

class DeathStarTest() {

    beforeTest
    void init() => station.chargeLasers();

    afterTest
    void dispose() => station.shutdownSystems();

    ...
}

Sometimes you want to temporarily disable a test or a group of tests. This can be done via the ignore annotation. This way the test will not be executed, but will be covered in the summary tests result. Ignore annotation can be used on test functions/methods, or on classes which contains tests, or even on packages or modules.

test
ignore("still not implemented")
void shouldBeFasterThanLight() {
}

All these features are of course supported in our Ceylon IDE. Where you can create a Ceylon Test Launch Configuration or easily select what you want to run in the Ceylon Explorer and in context menu select Run-As → Ceylon Test.

test-result-view

Test command

Our command line toolset has been enhanced by the new ceylon test command, which allows you to easily execute tests in specific modules.

The following command will execute every test in the com.acme.foo/1.0.0 module and will print a report about them to console.

$ ceylon test com.acme.foo/1.0.0

You can execute specific tests with the --test option, which takes a list of full-qualified declarations literals as values. The following examples show how to execute only the tests in a specified package, class or function.

$ ceylon test --test='package com.acme.foo.bar' com.acme.foo/1.0.0
$ ceylon test --test='class com.acme.foo.bar::Baz' com.acme.foo/1.0.0
$ ceylon test --test='function com.acme.foo.bar::baz' com.acme.foo/1.0.0

More details about this command can be found here.

Next version

In the next version, we will introduce other improvements.

There will be a test suite annotation, which allows you to combine several tests or test suites to run them together:

testSuite({`class YodaTest`,
           `class DarthVaderTest`,
           `function starOfDeathTestSuite`})
shared void starwarsTestSuite() {}

You will be able to declare custom test listeners, which will be notified during test execution:

testListeners({`class DependencyInjectionTestListener`,
               `class TransactionalTestListener`})
package com.acme;

And finally you will be able to specify custom implementation of the test executor, which is responsible for running tests:

testExecutor(`class ArquillianTestExecutor`)
package com.acme;

Please note, that these APIs are not final yet, and can change. If you want to share your thoughts about it, don't hesitate and contact us.

Ceylon 1.0.0 is now available

Today, we're proud to announce the first production release of the Ceylon language specification, compiler, and IDE. Ceylon 1.0 is a modern, modular, statically typed programming language for the Java and JavaScript virtual machines.

Ceylon enables the development of cross-platform modules that execute portably in both virtual machine environments. Alternatively, a Ceylon module may target one or the other platform, in which case it may interoperate with native code written for the platform.

In the box

This release includes:

  • a complete formal language specification that defines the syntax and semantics of Ceylon in language accessible to the professional developer,
  • a command line toolset including compilers for Java and JavaScript, a documentation compiler, and support for executing modular programs on the JVM and Node.js,
  • a powerful module architecture for code organization, dependency management, and module isolation at runtime,
  • the language module, our minimal, cross-platform foundation of the Ceylon SDK, and
  • a full-featured Eclipse-based integrated development environment.

ide screenshot

Language

Ceylon is a highly understandable object-oriented language with static typing. The language features:

  • an emphasis upon readability and a strong bias toward omission or elimination of potentially-harmful constructs,
  • an extremely powerful type system combining subtype and parametric polymorphism with declaration-site variance, including first-class union and intersection types, and using principal types for local type inference and flow-sensitive typing,
  • a unique treatment of function and tuple types, enabling powerful abstractions,
  • first-class constructs for defining modules and dependencies between modules,
  • a very flexible syntax including comprehensions and support for expressing tree-like structures, and
  • fully-reified generic types, on both the JVM and JavaScript virtual machines, and a unique typesafe metamodel.

More information about these language features may be found in the feature list and quick introduction.

This release does not introduce new language features. However, a very large number of bugs have been fixed.

IDE

Screenshots of the IDE may be seen here.

This release of the IDE introduces the following new features:

  • a type hierarchy view, to complement the popup type hierarchy,
  • a documentation view, to complement the documentation hover,
  • a new Ceylon Module properties page, and the ability to manage dependencies from this page or from the New Ceylon Module wizard,
  • enhancements to the search results view,
  • improvements to syntax highlighting in the hover,
  • a much improved wizard for importing Java archives into Ceylon module repositories, and
  • many bugfixes.

Community module repository

Ceylon Herd is now open to the public.

herd screenshot

SDK

The platform modules, recompiled for 1.0.0, are available in the shared community repository, Ceylon Herd.

This release introduces the following new platform modules:

  • ceylon.build, a framework for writing build scripts in Ceylon, and
  • ceylon.html, a library for defining HTML content in Ceylon.

Community

The Ceylon community site, http://ceylon-lang.org, includes documentation, and information about getting involved.

Source code

The source code for Ceylon, its specification, and its website is freely available from GitHub.

Issues

Bugs and suggestions may be reported in GitHub's issue tracker.

Acknowledgement

We're deeply indebted to the community volunteers who contributed a substantial part of the current Ceylon codebase, working in their own spare time. The following people have contributed to this release:

Gavin King, Stéphane Épardaud, Tako Schotanus, Emmanuel Bernard, Tom Bentley, Aleš Justin, David Festal, Flavio Oliveri, Max Rydahl Andersen, Mladen Turk, James Cobb, Tomáš Hradec, Michael Brackx, Ross Tate, Ivo Kasiuk, Enrique Zamudio, Roland Tepp, Diego Coronel, Daniel Rochetti, Loic Rouchon, Matej Lazar, Corbin Uselton, Akber Choudhry, Lucas Werkmeister, Julien Viet, Brent Douglas, Lukas Eder, Markus Rydh, Julien Ponge, Pete Muir, Henning Burdack, Nicolas Leroux, Brett Cannon, Geoffrey De Smet, Guillaume Lours, Gunnar Morling, Jeff Parsons, Jesse Sightler, Oleg Kulikov, Raimund Klein, Sergej Koščejev, Chris Marshall, Simon Thum, Maia Kozheva, Shelby, Aslak Knutsen, Fabien Meurisse, Paco Soberón, Sjur Bakka, Xavier Coulon, Ari Kast, Dan Allen, Deniz Türkoglu, F. Meurisse, Jean-Charles Roger, Johannes Lehmann, Nikolay Tsankov.

New Road Map

With the release of 1.0 beta, we reached the end of our previous roadmap. This doesn't mean we've run out of work to do, so of course we needed a new one. Here's a sketch of our plan:

Ceylon 1.0 final

The focus of development right now is of course bug fixes to the compiler backends, language module, and IDE. The major new feature planned for 1.0 final is serialization, which, even though we think of it as a language feature, is really, strictly speaking, a feature of the language module.

In parallel, David Festal is working on some very-needed optimizations to build performance in Ceylon IDE, though that work won't be finished in 1.0 final. I found the time this weekend to squeeze a couple of cool new features into the IDE, but that's not supposed to be the priority for this release.

There's also some issues we need to work through with interop between our module system and Maven. I'm not sure whether we'll be able to get this all sorted out in 1.0, or whether this will slip (again) to 1.1.

Finally, we hope to have a couple of new platform modules ready for the 1.0 final release, including ceylon.transaction.

Ceylon 1.1

Ceylon 1.1 will be all about performance, including language performance, compiler performance, and David's ongoing work on IDE build performance. There are a whole bunch of really obvious optimizations we can make, that we simply havn't had time to work on yet.

A warning: we expect to break binary compatibility between 1.0 and 1.1. That's not something we do lightly, and it's not something we plan to make a habit of. Changes affecting binary compatibility should occur in major releases, not minor releases. Please forgive us if we break our own rule this one time.

At the same time, building out the Ceylon SDK will also be a top priority. This will probably be what I personally focus on for a while.

Ceylon 1.2

Ceylon 1.2 will introduce a number of new language features. We're not completely sure of precisely which new features will make the cut, though we do have a shortlist of several which are almost certain to make it in. I'm not talking about major new features of the type system or anything here. We're really very happy with what's possible in the language as it exists today. The priority will be additional syntax for dealing with situations that are a little uncomfortable right now, and removal of a handful of limitations introduced temporarily for 1.0.

Here's a list of some of the things under very serious consideration for 1.2. Don't expect all of them to make the cut. We want to make the language easy to use. That means fixing things that suck without bloating out the language with too many overlapping features and minor syntax variations.

Ceylon 1.0 beta

After more than three years of development, Ceylon is now feature-complete. Ceylon 1.0 beta implements the whole language specification, providing the capability to execute Ceylon programs on both Java and JavaScript virtual machines and to interoperate with native code written for those platforms. This release includes:

  • a complete formal language specification that defines the syntax and semantics of Ceylon in language accessible to the professional developer,
  • a command line toolset including compilers for Java and JavaScript, a documentation compiler, and support for executing modular programs on the JVM and Node.js,
  • a powerful module architecture for code organization, dependency management, and module isolation at runtime, and
  • the language module, our minimal, cross-platform foundation of the Ceylon SDK.

Simultaneously, we're releasing Ceylon IDE 1.0 beta, the latest iteration of our full-featured Eclipse-based development environment.

runas

New features of the language

This release introduces the following new language features, along with many bugfixes:

  • annotations and annotation constraints,
  • a typesafe metamodel,
  • "static" method and attribute references,
  • try with resources,
  • support for strings, integers, and characters in switch,
  • support for named unicode characters in string and character literals,
  • the ** scaling multiplication operator,
  • nonempty variadic parameters, and
  • a new improved syntax for calling concrete members of inherited interfaces.

The new features are summarized here.

metamodel

New features of the IDE

This release of the IDE introduces performance improvements, many bugfixes, and:

  • support for launching Ceylon programs on the module runtime,
  • paste-with-imports, and autoindentation on paste,
  • integration with Eclipse's built-in file and package refactorings,
  • inline "linked-mode" rename, and rename support for references in documentation strings,
  • improvements to autocompletion, including "linked-mode" argument completion,
  • much improved integration for Eclipse's merge viewer,
  • integration with the commandline toolset's configuration file format,
  • several new quick fixes and assists, including new quick assists for adding and changing import aliases, and
  • a new editor preferences page.

You can see screenshots of the new release here.

autocomplete

rename

Community

The Ceylon community site includes documentation, and information about getting involved.

http://ceylon-lang.org

SDK

The platform modules, recompiled for 1.0 beta, are available in the shared community repository, Ceylon Herd.

https://herd.ceylon-lang.org

Source code

The source code for Ceylon, its specification, and its website, is freely available from GitHub:

https://github.com/ceylon

Issues

Bugs and suggestions may be reported in GitHub's issue tracker.

Acknowledgement

We're deeply indebted to the community volunteers who contributed a substantial part of the current Ceylon codebase, working in their own spare time. The following people have contributed to this release:

Gavin King, Stéphane Épardaud, Tako Schotanus, Emmanuel Bernard, Tom Bentley, Aleš Justin, David Festal, Flavio Oliveri, Max Rydahl Andersen, Mladen Turk, James Cobb, Tomáš Hradec, Michael Brackx, Ross Tate, Ivo Kasiuk, Enrique Zamudio, Roland Tepp, Diego Coronel, Brent Douglas, Corbin Uselton, Loic Rouchon, Lukas Eder, Markus Rydh, Matej Lazar, Julien Ponge, Julien Viet, Pete Muir, Nicolas Leroux, Brett Cannon, Geoffrey De Smet, Guillaume Lours, Gunnar Morling, Jeff Parsons, Jesse Sightler, Oleg Kulikov, Raimund Klein, Sergej Koščejev, Chris Marshall, Simon Thum, Maia Kozheva, Shelby, Aslak Knutsen, Fabien Meurisse, Paco Soberón, Sjur Bakka, Xavier Coulon, Akber Choudhry, Ari Kast, Dan Allen, Deniz Türkoglu, F. Meurisse, Jean-Charles Roger, Johannes Lehmann.

Ceylon M6 progress report

So it looks like it's time again for me to offer my usual lame excuses for another late milestone release of Ceylon. Well, I suppose all that really matters is: it's coming soon!

Ceylon M6 will be the first feature-complete implementation of the language specification, incorporating the following headline changes:

  • new syntax for invoking super-interface members,
  • nonempty variadic parameters
  • try with resources,
  • the ** scaling multiplication operator,
  • "static" member references,
  • metamodel and metamodel expressions, and
  • annotations.

We have not yet decided if support for serialization will make it into M6.

Invoking super-interface members

Previously, we were using a rather ugly and arbitrary syntax, for example, List::equals(that), to invoke an overridden member of a superinterface. Now we can just write:

super.equals(that)

except in cases where this is ambiguous (the member is ambiguously inherited from more than one supertype), in which case we can use the widening of operator to eliminate the ambiguity:

(super of List<T>).equals(that)

(We now treat super as a value whose type is the intersection of all immediate supertypes of the current type.)

Nonempty variadic parameters

You may now define a variadic function that requires at least one argument, for example:

String max(String+ strings) {
    value max = strings.first;
    for (string in strings.rest) {
        if (string>max) {
            max = string;
        }
    }
    return max;
}

The type of such a function is written String(String+), meaning, of course, Callable<String,[String+]>.

try with resources

This constuct works almost exactly like in Java. For example:

try (Transaction()) { ... }

Scaling multiplication operator

A top user request was support for "scaling" multiplication for vectors, matrices, durations, etc. We've introduced the interface Scalable and the ** operation to let you write things like:

Vector scaled = 2 ** vector;

Static member references

Static member references let us obtain a reference to a member of a type without providing an instance of the type. For example:

  • Person.name refers to the attribute name declared by the class Person, and
  • Object.equals refers to the method equals declared by the class Object.

The type of a static method reference is a function type where the first parameter list accepts an instance of the type that declares the member.

  • Person.name is of type String(Person), and
  • Object.equals is of type Boolean(Object)(Object).

Static attribute references are especially useful, since we can pass them directly to map():

Person[] people = .... ;
{String*} names = people.map(Person.name);

This functionality is already working.

The metamodel

We call Ceylon a "higher-order" language partly because functions, classes, methods, and attributes are typed values. For example, the class Person is a value of type Person(Name):

Person(Name) createPerson = Person;
Person person = createPerson(Name("Gavin", "King"));

However, Ceylon takes the notion of "higher-order" significantly further. The language lets us write typesafe code that reasons about the program itself, by providing a typesafe metamodel.

A metamodel expression is enclosed in backticks:

Class<Person,[Name]> personClass = `Person`;
Attribute<Person,Name> nameAttribute = `Person.name`;
Method<Object,Boolean,[Object]> equalsMethod = `Object.equals`;

We can use a metamodel to obtain the name and annotations of a declaration, or to query a type for members by their return type, parameter types, annotations, etc.

It's taking us a bit of work to get the metamodel just right, and that's the main thing that has been holding up the M6 release.

Annotations

Annotations are discussed here. The basic concept hasn't changed much in our initial implementation, but work is ongoing.