Thank you Nuria, it's a good feedback
You can read my answers after each point of the discussion...
Nuria Tejera a écrit :
Hello everyone, I
would firstly like to introduce myself. My name is Nuria Tejera and I'm
working for the company Open Canarias in the
ModelSet project, specifically on model to text transformations. These
past few weeks we have been talking (Jonathan and me) about
opening a debate on the specification of Mof2Text. He has taken the
initiative, so now it is my turn to share my research.
Firstly I wish to comment to you some of the ambiguities pointed out by
Jonathan.
- When an invocation creates an empty line : Does it mean that we have
to generate "\n" or ""?
Here I think the answer varies depending on where the empty line is
located. A transformation can be written according to the grammar in two
ways: text-explicit and code-explicit. In the case of code-explicit,
all whitespaces (tab, newline, etc.) should be omitted on the output
file.
In the other case, whitespaces written in blocks (ifblock, forblock,
templateblock, etc.) must be retained in the output file, but they
should be dropped outside templates and macros (for example, the "\n"
between imports, template definition, etc.).
I totally agree with you
- For the abstract syntax, there are a lot of namings and
multiplicities issues : "arguments" mustn't end with 's'
That's right.
So, I decided to rename the wrong references
- Can we use MANIFEST.MF files to declare dependencies between
generation modules? I would like to use the eclipse mecanism for
dependencies
but it is not compatible with the specification
I'm sorry, but I think I don't understand this paragraph. Are you
speaking about the compilation phase or when files have already been
generated? Perhaps you want to create files mtl in several different
plug-ins and want to express dependencies between them. In this case,
I think that this affects the implementation under Java and Eclipse
environment rather than the specification. Even so, it would be
important
to define a common mechanism to solve this kind of problems. Please,
could you elaborate?
The compilation phase creates a model for each mtl file... Now, I want
to reuse a template that is defined in another plugin... We can create
a physical reference between the models, using the URI mecanism of EMF:
- platform URI platform://MyProject/bin/myTemplate.emtl
- plugin URI plugin://MyPlugin/bin/myTemplate.emtl
- custom URI classpath://myTemplate.emtl
So, I need something like the classpath mecanism to resolve the
physical URI
I decided to use OSGI, but I think that it can be an interoperability
problem for those who want to reuse the MTL models in another MTL
tool....
- The delimiters of the protected area are not defined in the standard,
they don't want to make a choice. So, We have to choose the way to
keep the user code... We can use tags like : //Start of user code
//End of user code I would like to dicuss about the different
points of views?
The specification is not clear about this in how the parser must act
with protected areas but the "marker" is mentioned in the concrete and
abstract syntax. You could write something like this.
[module mymodule(http://www.eclipse.org/uml2/2.1.0/UML)/]
[template public operationToJava (c: Class)]
[for (p : Operation | c ->ownedOperation.type)]
public void [p.name/] () {
[protected ('// protected area '.concat(p.name))]
[/protected]
Ok, but Do you agree that the identifier of the protected area is the
whole line? We have to write "// protected area" at the begining of the
block and at the end... What's happening if my identifier is not
unique? The specification is ambiguous
}
[/for]
[/template]
In this case the delimiter is "// protected area OperationName". In
addition there can be no two delimiters with the same name in the output
file. The protected text associated with the delimiter generated
previously must be included in the next generation of output file.
- TemplateInvocation : The specification is ambiguous if the result is
not a string... Is it an error? Do We have to call the toString by
default?
I think that is not a mistake. From the outset I assumed that the
output file must contain ASCII characters. If for example the result of
a
template invocation is of type integer, the output file should contain
the textual representation of that number. So, I would say that the call
to the method toString() when the type of invocation is not a String is
required.
We made the same choice
- Module.import reference is missing in the metamodel... We decided to
create an import link in the metamodel...
At first I thought it was necessary to create an import link in the
metamodel. Now I am convinced that it's not necessary. The imported
modules are used in template and macro invocations. One possible
solution is to store a list of all modules that can be imported during
the syntax and semantic analisys. This list contains a link to the root
of each module.
When the analyzer finds a TemplateInvocation or MacroInvocation it must
look for the definition in the actual module or any of the imported
ones. If the analyzer finds it, the "definition" link should point to
the macro or module found. At the end of the analysis, the list of
imported
modules can be discarded as they are no longer needed.
In traditional languages like Java, the procedure is the same. You can
declare all imports that you want, but that does not translate into the
bytecode. Is only necessary at the compilation's phase.
Good point!!!!!!
- We need the position of the template element during the generation
(for the debugger) So, We defined a new element to store the
position information.
It's true that this information is necessary but I believe that there's
no need to modify the model to add it. For the implementation
of the parser I used the MDT OCL project. I've been using the LPG
parser to extend the grammar. Then, each element of MTL's metamodel
inherit ASTNode, which is present in the OCL's metamodel. This element
contains the information you're looking for.
We have done that, but, these information are transient in the OCL
plugin... You lose the position :-( Christian said that we can have
the position by using the CstToAst map of the OCL plugin... I have to
work with him on that point...
Finally I would like to add some ambiguities that I have detected.
1) Firstly, how to define the comments. According to the specification
can only be used line comments as Java (// upto the end-of-line).
Imagine a case like this.
[module mymodule(http://www.eclipse.org/uml2/2.1.0/UML)/]
// MTL comment
[template public operationToJava (c: Class)]
[for (p : Operation | c ->ownedOperation.type)]
public void [p.name/] () { } // ¿¿MTL comment or
Java comment??
[/for]
[/template]
As can be seen the parser can not distinguish whether the comment is a
text to discard or produce. That is why I believe we must change it and
use something that is different from most languages. For example [!--
For multiline comments --] that has not been defined and
/## for comments until the end of line. Any proposals?
At the moment we decided to use a new block [comment .... /]
It's a temporary solution
I like [!-- ...
--] !!!
Wim and Arjan? Do you think that's a good choice?
I don't agree for the single line comment because it isn't really
uniform with the other concepts of the specification
2) I found a reduce-reduce conflict between the following rules:
<OclExpressionCS> ::= ( <PropertyCallExpCS> |
<VariableExpCS> | <LiteralExpCS> | <LetExpCS> |
<OclMessageExpCS> |
<ifExp> | <invocation> )
<invocation> ::= ( <PathNameCS> '(' <actualarglist>
')' | 'super' ) [ <before> ] [ <separator> ] [
<after> ]
<actualarglist> ::= ( <OclExpressionCS> ( ','
<OclExpressionCS> )* )?
<before> ::= 'before' '(' <OclExpressionCS> ')'
<separator> ::= 'separator' '(' <OclExpressionCS> ')'
<after> ::= 'after' '(' <OclExpressionCS> ')'
The grammar has not been really tested by the OMG guys, it's a
fact!!! ;-) ;-) We'll bother Arjan...
You have to change the grammar Nuria
The OCL concrete syntax contains the following rules (see OCL
Specificacion. Pages 64, 72, 80 and 81)
OclExpressionCS ::= PropertyCallExpCS | VariableExpCS | LiteralExpCS |
LetExpCS | OclMessageExpCS | IfExpCS
PropertyCallExpCS ::= ModelPropertyCallExpCS | LoopExpCS
ModelPropertyCallExpCS ::= OperationCallExpCS | AttributeCallExpCS |
NavigationCallExpCS
OperationCallExpCS ::= OclExpressionCS[1] simpleNameCS
OclExpressionCS[2]
| OclExpressionCS '->' simpleNameCS '('
argumentsCS? ')'
| OclExpressionCS '.' simpleNameCS '('
argumentsCS? ')'
| simpleNameCS '(' argumentsCS? ')'
| OclExpressionCS '.' simpleNameCS isMarkedPreCS
'(' argumentsCS? ')'
| simpleNameCS isMarkedPreCS '(' argumentsCS? ')'
| pathNameCS '(' argumentsCS? ')'
| simpleNameCS OclExpressionCS
argumentsCS[1] ::= OclExpressionCS ( ‘,’ argumentsCS[2] )?
The conflict appears when the before, separator and after rules are all
empty at the same time in the <invocation> MTL rule.
In that case the resolution proceeds as follows:
OclExpressionCS ::= invocation ::= PathNameCS '(' actualarglist ')'
OclExpressionCS ::= PropertyCallExpCS ::= ModelPropertyCallExpCS ::=
OperationCallCS ::= pathNameCS '(' argumentsCS? ')'
The best solution I have found to avoid this conflict involves the
introduction of a new keyword, 'invoke'.
The invocation rule could be updated as follows:
<invocation> ::= invoke ( <PathNameCS> '('
<actualarglist> ')' | 'super' ) [ <before> ] [
<separator> ] [ <after> ]
This way we can distinguish easily between the two cases.
TemplateInvocation, MacroInvocation and QueryInvocation would then
always resolve unambiguously into this last rule.
Why the specification is so complex on that point? You're right!!! At
the moment, for our compiler, everything is an OCL _expression_ or a
"template invocation" ;-)
3) There is an inconsistency in the metamodel. The Mof2Text metamodel
couldn't attach static text to a body section. I will explain the
problem with the next example:
[template public TableToDDL(t: Table)]
CREATE TABLE [t.name/] (
[for (c:Column|t.column) separator(',')]
[c.name/] [c.type/]
[/for]
);
[KeyToDDL(t.key)/]
[ForeignKeyToDDL(t.foreignKey)/]
[/template]
The template body contains a ForBlock, a TemplateExpression ([t.name/])
and two TemplateInvocation (KeyToDDL and ForeignKeyToDDL).
The static text "CREATE TABLE", "(" and ");" doesn't attach in the
model. The OCL specification contains StringLiteralExpEVal class
that it could be used to attach the static text seen in the previous
example. So we could to modify the metamodel specification
to allow the body reference contain any OclExpression, for example,
StringLiteralExp
We have made that choice
The type of the "body" reference is "OCLExpression", and
"TemplateExpression" extends "OCLExpression"
Then, it is easier to define a "StringLiteralExp" in the body of the
template
Before:
--------- ----------------------
| Block | 1 ---------> 0..* | TemplateExpression |
--------- body ----------------------
Later:
--------- -----------------
| Block | 1 ---------> 0..* | OclExpression |
--------- body -----------------
4) I have also noticed another conflict with the following rule: The
parser does not allow zero or more contiguous OCLExpression
This does not happen in text-explicit mode. Here, the OCLExpression are
described in brackets.
<production_code>::= (<filecmd_code> | <literal_code>
|
<protected_code>| <tracecmd_code> | <forcmd_code> |
<ifcmd_code> |
<letcmd_code> | <OclExpressionCS> )*
euuuh, I'm not sure to understand the question ;-)
That's all, friends. I still have more things I would like to share
with you.
like me
But for now I'd rather not add
too much information at once,
by now it is enough.
I agree
I would appreciate any kind of
feedback about
these questions. The specification is still in beta and needs to be
improved.
Regards, Nuria Tejera (netverde@xxxxxxxxxxxxxxxx).
Thank you,
I'm really happy to see you on the mailing list...
Regards,
Jonathan
|