Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "RoadmapOAW5"

Line 136: Line 136:
  
 
The static semantics are straight forward: The guard must be of type boolean.
 
The static semantics are straight forward: The guard must be of type boolean.
 +
 +
====Extensions overwrite semantics====
 +
Extensions with the same signature will overwrite Operations.
 +
Consider overwriting the toString() Operation  (which is invoked on String concatenations) for arbitrary meta types.
 +
This will allow very readable templates.
 +
 +
  
 
=== Code blocks ===
 
=== Code blocks ===
Line 220: Line 227:
 
       }
 
       }
  
 +
 +
=== XString (Template syntax) ===
 +
We want to come up with a special datatype calle XString, which has a special literal syntax (like Xpand template syntax) and is mutable and streamable.
 +
 +
Example:
 +
  toJava(Entity this) :"""
 +
    package «packageName()»;
 +
     
 +
      public class «name» {
 +
        «FOREACH attributes AS a»
 +
        public «a.type» «a.name»;
 +
        «ENDFOREACH»
 +
      }""";
 +
 +
It's just a string literal with the xpand syntax within. The terminals '«' and '»' should be configurable (or there should be an alternative at least).
 +
 +
The FILE statement will be removed.
 +
Files can be opened through extensions:
 +
 +
  generateCode(Entity e) :
 +
    writeToFile(e.JavaFile(),e.toJava());
 +
 +
==== Container (NOT CLEAR HOW THIS COULD WORK) ====
 +
Because XStrings are mutable and are converted to a string late, it is possible to create a ree structure containing XStrings, where
 +
you can add XStrings (or normal Strings) later on.
 +
 +
Example:
 +
  toJava(Entity this) :"""
 +
      package «packageName()»;
 +
      «imports()»
 +
 
 +
      ...
 +
  """;
 +
 +
  cached imports(Entity this) :"""
 +
      import java.util.*;
 +
  """;
 +
 
 +
... to be continued (and cleaned up;-))
  
  
Line 228: Line 274:
  
 
The else part is optional and will return null if not defined.  
 
The else part is optional and will return null if not defined.  
The following expression will return null:
 
  if (false) "Holla"
 
  
===Integration of Check===
+
Example:
 +
  // The following expression will return null:
 +
  if (false) "Holla"
 +
 
 +
===Declarative constraints===
 
The language check will be integrated into Xtend. That is you can define checks and extensions in the same file:
 
The language check will be integrated into Xtend. That is you can define checks and extensions in the same file:
  
 
  allEntities(emf::EObject obj) : eRootContainer.eAllContents.typeSelect(Entity);
 
  allEntities(emf::EObject obj) : eRootContainer.eAllContents.typeSelect(Entity);
 
   
 
   
  context Entity {
+
  context Entity warning "name "+name+" should start with an uppercase letter" :  
    warning "name "+name+" should start with an uppercase letter" :  
+
 
       name.firstToLowerCase()!=name
 
       name.firstToLowerCase()!=name
    error "duplicate name "+name :  
+
context Entity error "duplicate name "+name :  
 
       allEntities(this).select(e|e.name==name).size==1;
 
       allEntities(this).select(e|e.name==name).size==1;
}
 
  
 
of course you can use everything we have defined before in checks, too. Example :
 
of course you can use everything we have defined before in checks, too. Example :
  
 
+
  context Entity error "duplicate name "+name {
  context Entity {
+
  error "duplicate name "+name {
+
 
       var entities := eRootContainer.eAllContents.typeSelect(Entity);
 
       var entities := eRootContainer.eAllContents.typeSelect(Entity);
 
       allEntities(this).select(e|e.name==name).size==1;
 
       allEntities(this).select(e|e.name==name).size==1;
  }
+
}
  
=== Definition of Types ===
+
=== Definition of Types (later) ===
 
So far we couldn't define Types within Xtend but had to define them using other techniques (ecore, Java, UML-profile, etc.).
 
So far we couldn't define Types within Xtend but had to define them using other techniques (ecore, Java, UML-profile, etc.).
 
Defining tyoes within Xtend would be a great feature. Because it is much simpler and faster to write them in text.
 
Defining tyoes within Xtend would be a great feature. Because it is much simpler and faster to write them in text.
Line 281: Line 325:
 
   }
 
   }
 
  }
 
  }
 
=== Template syntax ===
 
We want to come up with a simple template syntax integrated into Xtend.
 
Example:
 
  context Entity {
 
 
 
    toJava() :
 
    »package «packageName()»;
 
     
 
      public class «name» {
 
        «attributes.each(a|»
 
        public «a.type» «a.name»;
 
        «)»
 
      }«;
 
 
It's just a string literal with the xpand terminals '«' and '»'.
 
In addition if you use these type of string literals, string concatenation is implicit.
 
Under the hood we might come up with a special string type (for performance reasons), but it should be compatible to the oaw String type and therefore transparent to the user.
 
 
Files are opened thorugh extensions:
 
 
 
  generateCode(Entity e) :
 
    writeToFile(e.JavaFile(),e.toJava());
 
 
 
Something like this...
 
 
===Extensions overwrite semantics===
 
Extensions with the same signature will overwrite Operations.
 
Consider overwriting the toString() Operation  (which is invoked on String concatenations) for arbitrary meta types.
 
This will allow very readable templates.
 
 
 
===Optional parentheses for operations, functions, extensions without parameters===
 
We should discuss if we want to make empty parentheses on invocations of operations optional.
 
So that :
 
  my.operation()
 
equals
 
  my.operation
 
 
 
=== Xpand Container ===
 
We'll have a possibility to add a string to a previously defined "outlet"
 

Revision as of 08:29, 13 November 2007

Collection of features (rough)

In Version 5 we want to improve some of the Xtend language concepts and features. Codename is Xtend++ :

Imports

The import mechanism should be overworked, so that every import is explicite. We won't need any metamodel configuration in the workflow nor in the editors anymore. This will not only make the setup simpler but will also improve the performance.

The syntax would change to something like the following:

import org:openarchitectureware:Extension; // native import
import EMF "my/package/model.ecore"; // non-native import
import UML "my/test.profile.uml" as profile; // non-native import with name space definition
import Java "my.test.Class"; // non-native import introduces java types and features form my.test.Class
import XSD "http://www.mywebsite.org/xsd/metamodel.xsd" // non-native import importing the types from an XSD file
... (think of Hibernate mapping files, Groovy, etc.)

Native import

A native import refers to another extension file imports all public members (types, functions, extensions).

Non-native Import

A non native import starts with an identifier pointing to an installed adapter. The adapter is responsible for loading and converting the type information from the given string. The syntax in the string is defined by the adapter.

Namespace definition

All members are included without namespace information. If you need a namespace you can explicitely define one per import.

Reexport

The reexport keyword will be supported.

Generics

We need full-fledged generics, which can conceptually be copied from Java's generics. Maybe we can leave out some of the more advanced capabilities?

Closures

We'll have real closures, not the built-in stuff we have now. Closure syntax:

  parameterList '|' expression-using-parameters-and-scope

Where parameter list must be typed, either implicit or explicit.

Example:

  // type of e is inferred from the declaration of the 'select()' function
  myList.select(e|e.name == "test")

or

 {
   String myText := "test";
   (Attribute)=>Boolean myClosure := e|e.name==myText;     // e is inferred from the declared type of the assignee
   myList.select(myClosure);
 }

alternatively declare the parameter types explicitly

 {
   var myText := "test";
   var myClosure := Attribute e|e.name==myText;
   myList.select(myClosure);
 }


Declaring Closure types

The syntax for of a closure type is

  (parameterTypes)=>returnType

Examples:

  ()=>Object
  (String)=>Boolean
  (String, Entity)=Entity

Example 2: declaration of higher-order functions using generics :

 List<T> select<T>(List<T> this, (T)=>Boolean closure) {
   ...
 }

Extensions/Functions

In the first version there will only be functions (aka. extensions). Functions can be invoked either using the functional syntax or using the member syntax (operation like):

  myFunction(foo, bar) == foo.myFuntion(bar)

A function is declared as follows:

  (private|cached) ReturnType? functionName(declaredParameterList) guardExpression? : bodyExpression ;

Example:

  private doStuff(Entity this) name!=null :
     name+"Stuff";

or

  (private|cached) functionName(declaredParameterList) guardExpression blockExpression

Example:

  cached makeAbstract(Entity this) {
     abstract := true;
     name := 'Abstract'+name;
     return this;
  }

Polymorphic Guards

The guards are used for polymorhpic resolution of a called extension.

Example:

context Entity {
   String javaName() isAbstract : "Abstract"+name;
   String javaName() : name;
}

The dynamic semantics are:

  • First select all possible features (functions and operations), based on the name and the types.
  • Then order those features by parameter types (best match first).
  • For each feature
  • evaluate the guard
  • if it doesn't evaluate to true skip it
  • if it evaluates to true
  • make sure that there is no second feature with the same signature where the guard evaluates to true
  • if there is no such feature, we've found our feature -> success!
  • else throw new Exception("Unambigous feature ... more than one feature ... bla")
  • if there are features, but the guards evaluate to false, return null:
  • if there is no feature, do "feature not found" (i.e. raising exception or invoking 'featureNotFound' operation)

The static semantics are straight forward: The guard must be of type boolean.

Extensions overwrite semantics

Extensions with the same signature will overwrite Operations. Consider overwriting the toString() Operation (which is invoked on String concatenations) for arbitrary meta types. This will allow very readable templates.


Code blocks

A code block is the replacement for chain expressions ( a-> b-> x) with the additional features:

  • provides variable declarations (Expression returning the assigned value)
  • support early exit using the 'return' keyword, which forces outer code blocks to exit themselfes.

It's something like a pseudo imperative syntax (but still is an expression!).

Example:

 myExtension(String stuff) {
    var x := stuff.length();
    if (x>56)
       return "Foo";
    else {
       return "Bar";
    }
 }

A code block is itself an expression consisting of a list of expressions. It returns the value returned by the first executed "return-expression", or the value of the last expression.

It is possible to overwrite the scope. Example:

doStuff() {

  var x := "Foo";
  {
     var x:= "Bar";
     return x;
  }

}

will return "Bar"

Object creation expression

We are thinking about a syntax to create model graphs inline. We need this not only for model transformations but also for writing model transformation tests.

Example:

  new Entity {
      name := "Person";
      references += new Reference {
         name := "someRef"
         type := anotherEntity
      }
  }

Assignment Expressions

They are just another syntax for invoking a setter resp. adder-operation (which will be removed). They return the assigned value.

create / cache semantics

The creation expression should replace the "create extension" mechanism from Xtend 1.0. A creation of an Object is cached if the type name is suffixed with parenthesis containing any number of arguments. The arguments act as a key.

Examples:

  var paramPerOperationAndName := new Parameter(op,name) {
     this.name := name;
     type := aDatatype;
  } 
  var localSingleton := new Foo() {
     stuff := "bla";
  }

cross referencing

We need a way to specify cross references within a declared tree. The problem is that we need a reference to a created type after it has been created and before it will be initialized. This can be accomplished by adding a special assignment construct:

  var x := new localRef:=Entity {
     // x is not visible here, because the right hand expression has not been evaluated so far.
     // localRef holds a reference to the created but not yet initialized entity.
        name := "Person";
        references += new Reference {
           name := "partner"
           type := localRef
        }
     }


XString (Template syntax)

We want to come up with a special datatype calle XString, which has a special literal syntax (like Xpand template syntax) and is mutable and streamable.

Example:

  toJava(Entity this) :"""
    package «packageName()»;
      
     public class «name» {
       «FOREACH attributes AS a» 
        public «a.type» «a.name»;
       «ENDFOREACH»
     }""";

It's just a string literal with the xpand syntax within. The terminals '«' and '»' should be configurable (or there should be an alternative at least).

The FILE statement will be removed. Files can be opened through extensions:

 generateCode(Entity e) :
    writeToFile(e.JavaFile(),e.toJava());

Container (NOT CLEAR HOW THIS COULD WORK)

Because XStrings are mutable and are converted to a string late, it is possible to create a ree structure containing XStrings, where you can add XStrings (or normal Strings) later on.

Example:

  toJava(Entity this) :"""
     package «packageName()»;
     «imports()»
  
     ...
  """;
  cached imports(Entity this) :"""
     import java.util.*;
  """;
  

... to be continued (and cleaned up;-))


if expression

As seen in the previous example, we want an if-expression. using if, else keywords.

if (predicate) expression (else if (predicate) expression)* (else expression)?

The else part is optional and will return null if not defined.

Example:

  // The following expression will return null:
  if (false) "Holla"

Declarative constraints

The language check will be integrated into Xtend. That is you can define checks and extensions in the same file:

allEntities(emf::EObject obj) : eRootContainer.eAllContents.typeSelect(Entity);

context Entity warning "name "+name+" should start with an uppercase letter" : 
      name.firstToLowerCase()!=name
context Entity error "duplicate name "+name : 
      allEntities(this).select(e|e.name==name).size==1;

of course you can use everything we have defined before in checks, too. Example :

context Entity error "duplicate name "+name {
      var entities := eRootContainer.eAllContents.typeSelect(Entity);
      allEntities(this).select(e|e.name==name).size==1;
}

Definition of Types (later)

So far we couldn't define Types within Xtend but had to define them using other techniques (ecore, Java, UML-profile, etc.). Defining tyoes within Xtend would be a great feature. Because it is much simpler and faster to write them in text. In addition we could define Type with logic (operations). A syntax could look like this:

type Entity extends Named {
  // simple attributes
  String name;
  Boolean isAbstract {
     private set(aValue)
     get : name.startsWith("Abstract");
  }; 
 
  // references
  Set<Entity> superTypes;
  Set<Features>* features; // asterisk means containment
  Set<Reference>* references subsets features;
  
  // operations
  doStuff(String x) : x+name;
  doMoreStuff(String x) {
     name := x;
     features += var f := new Feature{
                     f.name:= x;
                     ...
                 };
  }
}

Back to the top