7 comments
thanks for reply, and i know this extension language,but as far as i know, it only works for static extension method, while xtend has a local extension method which can even use a instance field as extension provider.
   actually i'm trying to implement this local extension method using MPS(just for execise), but i find that i have not this skill to do that(typesystem issue). by the way, can you reply the previous ExtractStatementListExpression question?
0
Hi John, could you elaborate on what kind of issue you're having, please?
At first, it looks like you're asking a general question, but then if you have some specific issue I could end up telling things that are obvious for you if I tried to say how I'd do this in general.
Have you done (or understand how to do) the AST, scoping and generator part of extension methods and only have problems with typesystem?
0
Hi Daniil, thanks for the reply

i will discribe my attempt till now very detailed,
and i just focus on the local field extension provider.

first i create a Extension node attribute:

  concept Extension extends NodeAttriute
    attributed concepts: FieldDeclaration

then i create a ExtensionFieldMethodCall concept:
  concept ExtensionFieldMethodCall extends InstanceMethodCallOperation   

and the constrains for link {instanceMethodDeclaration}:
    find all the FiledDeclaration with Extension attribute, and all the declared method which first param type :==: DotExpression.operator

and the generator for DotExpression
  condition: node.operation.isInstanceOf(ExtensionFieldMethodCall) ==>

  extensionField.methodCall(operator, actuallParams)

till now all works for me,
first i got a "wrong number of parameters" error,
and of course , the first param is not here, so i copy and modify the checking rule, and it works.
(i must set checking rule's overrides attribute to true!)

then i got the param type checking error. i just copy and modify the InstanceMethodCall's typeof_rule, but the code is too long and too complicated and i can not done that(i just skip and comment it).

so my situation now is i can mark a field as extension, and i can call the extension method, and also i can generate right java code.
  but i can not check the param type, can not chain the ExtensionFieldMethodCall.

please see the attactd source code, sorry i still not to know how to upload to github.

com.hpay.language.javaExtensions.rar (192KB)
0
first i create a Extension node attribute:

  concept Extension extends NodeAttriute
    attributed concepts: FieldDeclaration

then i create a ExtensionFieldMethodCall concept:
  concept ExtensionFieldMethodCall extends InstanceMethodCallOperation   

...


Everything looks very good. Except I wouldn't inherit from InstanceMethodCallOp, rather have it separate instead. Yes, structurally they're the same: both only have a reference to a method decl. But semantically different. This way you wouldn't have to fight every place in the existing code that works with InstMethodCalls. You found a couple immediately (checking rules, typing rules) but there are more.

So, ExtensionMethodCall extends BaseConcept implements IOperation. And probably not IMethodCall, because it does the argument count check.

Now, you would have to implement your own checking/typing rules. Unfortunately, as far as I know there is no easy way to reuse the typing rule for InstMethCall per se. So, copying it and gradually editing to your needs is probably the way to go.

Of course, it isn't good from software engineering point of view, as the two instances of that code may diverge, but... But then again, there might be some peculiarities with extension method calls that need to be addressed specifically, in their own typing rule.

I think type checking method calls is easily the most complicated aspect of java type system, due to generics. That's why the code there is what it is. So, you have to carefully go through it and change according places.
For example,
  instanceType :==: typeof(mcallop.getOperand())
prettyPrint();
should be replaced with something like
  instanceType :==: typeof(...extension provider field...)
prettyPrint();

Of course, you would also need to change iterations over argument lists. Try it and we'll see what problems come next.
0
yes, indeed that inherit from IMethodCall cause many problems, so here is my changes:

interface concept IExtensionMethodCall extends IOperation

  children:
  actualArgument: Expression[0..n]
  typeArgument  : Type[0..n]

  reference:
  baseMethodDeclaration: BaseMethodDeclaration[1]
prettyPrint();
concept ExtensionFieldMethodCall extends BaseConcept
  implements IExtensionMethodCall

  reference:
  instanceMethodDeclaration : InstanceMethodDeclaration[1] specializes: baseMethodDeclaration
prettyPrint();
and i must copy IMethodCall's editor component:
   IMethodCall_typeArguments -> IExtensionMethodCall_typeArguments
   IMethodCall_actualArguments -> IExtensionMethodCall_actualArguments

then i need add typesystem rules to IExtensionMethodCall,because i'm still can not handle generics, so i just write a simple rule:
node<> retType = mdecl.returnType; 
infer retType :<=: typeof(mcall);

final nlist<> argTypes = new nlist<>; 
foreach a in mcall.actualArgument { 
  argTypes.add(typeof(a)); 
} 
   
nlist<> typel = mdecl.getTypeApplicationParameters(mcall.actualArgument.size + 1).skip(1).toList; 
   
foreach type in typel, argt in argTypes { 
  check(argt :<=: type); 
}
prettyPrint();
and it works, but not support generics(it will take time to familiar with that).

by the way ,use IExtensionMethodCall interface concept, i can easily add extension local method support and extension library method support very quickly.

so, i think i have made a real progress,
thanks very much!
0
"Caught exception xxx is never thrown in the corresponding try block"

i got this error when i call a extension method in try block, i try to resolve this but found that i cann't.

the code in Statement_Behavior's collectUncaughtMethodThrowables method:
arg.descendants<concept = IMethodCall>.selectMany({~it => it.baseMethodDeclaration.throwsItem; }).union(arg.descendants<concept = DefaultClassifierMethodCallOperation>.selectMany({~it => it.method.throwsItem; })).where({~it => it.isInstanceOf(ClassifierType); }).forEach({~throwable => throwables.add(throwable : ClassifierType.classifier); });
prettyPrint();

it collect the throwsItem from IMethodCall and DefaultClassifierMethodCallOperation, and i can not override this function to add IExtensionMethod's throwsItem.


i think baseLanguage should add interface IThrowable, which have a method "getThrowsItem", then change the collectUncaughtMethodThrowables method to :
args.descendants<concept = IThrowable>.selectMany({~it => it.getThrowItems()})......
prettyPrint();

or any other option?
0

Please sign in to leave a comment.