November 20, 2008, 07:49:16 am *
News:
 
   Home   Help Search Login Register  
Pages: [1]
  Print  
Author Topic: Inference of variables in .QL  (Read 2593 times)
equim
Newbie
*
Posts: 2


« on: May 16, 2007, 10:36:18 pm »

Hi,

After spending 30 mins or so trying out some queries I quickly grew tired of having to declare every variable before using it.  Specifically, when a variable is assigned to it seems like I am just "filling in the blanks" for the .QL interpreter.  I found myself using the code completion feature to find the method I wanted to use, then invoking it again just to find the exact name of the return type, then typing that in to a totally different place (i.e. at the top of the query).

The code completion feature helps make writing queries enjoyable but having to add in these variable declarations seems to drain the fun away.

Could the declaration of the variables be made optional and automatically inferred by the return type of the right hand side of the assignment?  For example, could you make it so when I type myPackage = myMethod.getPackage() in the where section of the query myPackage is automatically inferred to be of type Package.  If not, could you at least make it so we can declare the variable when it is assigned to, i.e. Package myPackage = myMethod.getPackage()?

Thanks for the great work so far (and the prompt responses to my bug reports).  This is a promising product!

Martin
Logged
Oege de Moor
Newbie
*
Posts: 30


« Reply #1 on: May 18, 2007, 09:27:24 am »

Martin, thanks for the feedback.

Yep, that's certainly technically possible; in fact we already have a complete type inference engine under the hood that works out types whether variables are declared or not.

But I'm not totally convinced making declarations optional is desirable. First, "declare before use" makes queries easier to read (even if it's a little tedious to have to write it). Second, what should we do about auto-completion if we went this route? When one first types "p." without declaring p, there are no sensible suggestions to give. Similarly, while messing about with a query, it is common that at an intermediate state, the type inferencer decides there is *no* type for a variable. If you declared that variable, at least we know your intention and we can try to use that for auto-completion on the ill-typed query. But without such hints, autocompletion  will fail miserably.

So it's a trade-off, and I believe allowing  undeclared variables could give strange non-intuitive behaviour in the query editor [OK, it sometimes does that now, but at least there's hope of making it better  Wink ].

What do others think?
Logged
KirillOsenkov
Newbie
*
Posts: 11


« Reply #2 on: May 18, 2007, 02:58:36 pm »

Well, there could probably be an option of auto-inserting the inferred variable declaration as it is being typed in.

For example, I'm typing in a new variable, and as soon as the type of the variable can be inferred, the resolver should check if such a variable is already defined above - if not, it should automatically insert the definition text and bring the cursor back where it was.

If you implement this feature, make sure one can turn it on or off in the options.

P.S. Although implementing this would definitely be tricky - I already imagine walking the AST back and forth to find the place where to put the definition.

P.P.S. And another problem with this approach could be: how do we know that the user has finished typing in the variable usage? How do we know when to start inferring? When the caret has left the line? After pressing Enter? Or should the user be able to manually invoke inserting definition by pressing, say, Tab or F3?
Logged
equim
Newbie
*
Posts: 2


« Reply #3 on: May 19, 2007, 10:30:10 pm »

The way I see it, the from part of the query should be specifying the source (e.g. "all methods").

The ability to extract data from the results and store it in a variable within the where part seems to be something completely different.

As an example, I have the following query:

Code:
from Method uncalled, RefType uncalledType, Package uncalledPackage
where not exists(Callable caller | caller.getACall() == uncalled)
and uncalledType = uncalled.getDeclaringType()
and uncalledPackage = uncalledType.getPackage()
select uncalledPackage, uncalledType, uncalled
order by uncalledPackage, uncalledType, uncalled

All I'm doing here is attempting to get all uncalled methods and display them in a tree view grouped by package and type.  It doesn't seem right that I have to declare the temporary helper variables (uncalledType, uncalledPackage) in the from clause next to the source.

I might be wrong but from what I've seen so far assignments in the where statement are just used to allow an expression to be re-used in later parts of the query (without having to retype the whole expression multiple times).

I hope that's made my point of view a bit clearer.

Quote
First, "declare before use" makes queries easier to read
I'd have to disagree with that.  Having "RefType uncalledType, Package uncalledPackage" in the from clause above doesn't seem very helpful.  If the intent is to make the type of a variable explicit then surely the declaration should be next to the use?  I think it would be much more helpful to show a tooltip displaying the (infered) type of a variable when the mouse is hovered over it.

Quote
Second, what should we do about auto-completion if we went this route? When one first types "p." without declaring p, there are no sensible suggestions to give
That should be exactly the same as it is now.  If the type of p cannot be inferred (which I assume can only be the case if it hasn't been assigned to) then the error "p cannot be resolved" should be given, just as it is now if p has not been declared.  In fact, that would give you better error checking than you currently have, as you don't currently tell the user if they have not assigned to a variable (since you have to assume the user wanted to select all variables).

Quote
Similarly, while messing about with a query, it is common that at an intermediate state, the type inferencer decides there is *no* type for a variable. If you declared that variable, at least we know your intention and we can try to use that for auto-completion on the ill-typed query. But without such hints, autocompletion  will fail miserably.
Well I'll have to give you that.  I can't really say whether this would be a problem in practice without trying it.  I would have thought it would just be the same as it is now.  If the declaration cannot be read as the query is in an intermediate state then you can't show the autocompletion list.

Kirill's suggestion could be used, although I would have a declaration changing along with the inferred type (unless doing so would take the query into an error state).  Either that or it could work similarly to Eclipse's "Organize imports" command which would insert the correct declarations when the user asks for it (from a toolbar icon, a menu item or a shortcut key)

Martin
Logged
Oege de Moor
Newbie
*
Posts: 30


« Reply #4 on: May 29, 2007, 08:26:37 am »

A feature analogous to "organize imports" sounds an excellent plan. We'll put it on the list.
Logged
Pages: [1]
  Print  
 
Jump to: