[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
| Re: [m2t-dev] [backend] bugs and thoughts | 
Laurent,
First of all, let me apologize, this will be a lengthy mail :D.
not at all - quite the contrary, I found it pretty concise and to the point.
1) I found the IfExpression you have defined in the backend for the 
control flow. But there isn't any cases such as "an if with no else" (I 
think such use cases could be  handled by creating an "if" with an 
LiteralExpression containing an empty String as the else, but it would 
be better to have the backend perform this transparently) or "if - else 
if - else". What is the expected way to implement this last use case? An 
"if" with another "if" as the statement when false? Or simply using a 
SwitchExpression that seems to present the right behavior?
The backend is thoroughly functional - there are no statements but only 
expressions, which by definition always return a value. So an "if 
without else" makes no sense in this paradigm.
The SequenceExpression serves the purpose of "executing" several 
expressions one after another, statement-like. It treats all expressions 
except the last as "statements", i.e. it discards their return values 
and executes them only to have their side effects.
2) This might be the most annoying one I have faced since so hard to 
track down : When using a CompositeTypeSystem, getting functions from a 
java file through MiddleEnd#getFunctions() fails in NPE with the root 
being the first line of JavaBeansType#init() :
  - _superTypes = Collections.singleton (ts.getRootTypesystem().findType 
(_javaClass.getSuperclass()));
It so happens that one of the java class as no superClasses, thus 
_javaClass.getSuperclass() returning null and the execution failing 
later on. I have had to completely comment out all of the lines of 
CompositeTypeSystem that references the field _javaBeansTypesystem in 
order to get rid of the error (I do not need the java beans types for my 
use case ... why didn't you create a typeSystem for java beans as you 
did for EMF, one that can be registered if needed and that isn't used 
otherwise).
I do not understand this yet, but it vaguely sounds as if you are using 
things differently from the way I intended them to be used. If you send 
some code or explain some more, I will be happy to look into it and 
advise you.
The reason why the Java type system is built-in is that Java is the only 
language to actually implement "native" functions, and it is used 
internally. This may not be necessary at some time in the future - but 
that should be transparent, and there should be no situation when it 
actually gets in the way - at least that's what I hope and intend ;-)
3) You have defined a SequenceExpression that is described on the wiki ( 
http://wiki.eclipse.org/M2TBackend ) as being "the subsequent execution 
of several expressions"... yet I am puzzled by its implementation :
   protected Object evaluateInternal(ExecutionContext ctx) {
           Object result = null;
           for (ExpressionBase e: _inner)
               result = e.evaluate(ctx);
           return result;
   }
The only result we'll get ... is the result of the very last statement's 
evaluation since "result" is overriden by each new evaluation. Is that 
how it is intended? If yes, is there an expression that has been defined 
to allow us to have the backend execute a sequence of expressions (let's 
say two LiteralExpression) and get the result of both evaluations? The 
use case I have is similar to (forgive the errors, I've never used xpand 
:D) :
   «DEFINE function FOR uml::Element-»
       «IF name != null-»
           Element : «name»
           Element type : «eClass»
       «ENDIF»
And I would like to define the backend expressions needed : an 
IfExpression with a condition, but what can I use as the "then part" of 
this IF if not a SequenceExpression?
In the example you included, the then part is about concatenating the 
results of several expressions into a single string. This is done using 
a system library function - look into the Xpand middleend implementation 
which does just this. This is *not* a situation for a SequenceExpression.
4) On to the Type System. You have provided us the way of defining new 
BackendTypeSystem through the CompositeTypeSystem#register() method. In 
the same fashion, you provided us with a way of defining new BackendType 
and to tell that such or such BackendType is assignment compatible with 
another through BackendType#isAssignableFrom(). This is perfect ... but 
what if I tell that RandomType is assignment-compatible with String? The 
backend will fail to invoke functions defined with parameter of type 
"RandomType" with a String parameter since it doesn't know how to 
convert from String to Random.
We then need a way to provide our own converters, the same way you did 
with the JavaBuiltinConverterFactory. What I did for now is "hack" my 
way through by adding a method "addConverter" to the 
JavaBuiltinConverterFactory and providing it with as key the Class on 
which the converter applies, and as value the converter itself 
(extending JavaBuiltinConverter). This doesn't seem like a solution that 
could be applied since all types that need conversion are not mandatory 
java.
I think type conversion should be handled by the BackendTypeSystem 
itself when we provide it. Maybe we could discuss this a little further? 
This truly is a blocking issue if we decide to use the backend for our 
project (hence the "hack" I implemented to carry on my tests). Except if 
I deeply misunderstood something (which can be the case :p).
You are right, there is currently no way to register implicit type 
conversions. It is a powerful feature, and I somewhat like the idea of 
adding it, but it is extremely complex to integrate in a conceptually 
clean way.
What you want is different from the JavaBuiltin stuff. The JavaBuiltin 
stuff works only at the fringes of the system, i.e. when Java functions 
are called, becasue there are several integer types in Java but they are 
all represented by java.lang.Long in the backend.
You on the other hand probably want implicit type conversions for 
function calls inside the backend (with conversions when a Java function 
is called only as a special case), right?
Would you view such assignment compatibility as a part of a type 
definition, introducing static dependencies between the types? Or would 
you see it as something introduced by a certain compilation unit, giving 
it a limited scope?
5) Each of the Expressions provided by the backend need a "SourcePos" 
object which seems to hold information on the source template and the 
line number where we are located. Is this intended for debugguing 
purposes? I couldn't find documentation on these.
SourcePos is a placeholder to support debugging, logging etc. - it is 
currently largely transparent to the backend, and we will see what 
information exactly is needed for this purpose.
6) Last but not least, some languages define functions with varargs. 
This can happen in M2T languages (Acceleo comes in mind) as well as in 
programming languages (Java 5 and function defined as "public void 
varargs(Object... args)"). How are these dealed with by the backend? Or 
if they are not, is there even plans to support such feature?
varargs are at the level of the concrete syntax, not of the backend. If 
you want varargs, just add a List parameter in the backend and transform 
accordingly.
That's all there is for this mail, hope you are not sleeping or in need 
of an aspirin by now ;).
Oh, not at all. I am really glad for your feedback - it helps making the 
backend meaningful for several languages, and your different way of 
thinking and requirements are really interesting.
Have fun
- Arno
--
Arno Haase
Langemarckstr. 16
53227 Bonn
Mobil: +49 160 98525085
Tel:   +49 228 9654443
Fax:   +49 228 9654448
Attachment:
signature.asc
Description: OpenPGP digital signature