Playing with the QML/JS plugin

Sven Brauch svenbrauch at
Tue Apr 8 08:24:44 UTC 2014


On Tuesday 08 April 2014 09:55:11 Denis Steckelmacher wrote:
> * The type inference system has to build types (functions, objects), and
> some of these types require an internal context. Creating these types
> and contexts may be easier in a subclass of AbstractTypeBuilder and
> AbstractContextBuilder, even if it is possible to split the creation of
> the types and the creation of the contexts, like what was done for
> functions (their context is created in ContextBuilder, their type in
> ExpressionVisitor).
There's a difference between *creating* the types (i.e. determining them and 
instantiating the type objects) and *assigning* those types to declarations. 
The idea is that the expression visitor only determines and creates the type, 
and then the caller (e.g. declarationbuilder) can do with it whatever he wants 
-- for example assign it to a declaration.
Just creating the types has no side effects, you're just allocating a few 
objects which will be deleted again. You only alter the state of the language 
database if you set those types on a declaration using setType or similar. So 
creating the types in the expression visitor is kind of independent of what 
the caller does with them then.

> * ExpressionVisitor only computes the types of what it is asked to,
> which is good, while my version of DeclarationBuilder computes the type
> of every node. One advantage of DeclarationBuilder, though, is that it
> has a strict O(n) complexity : every node is visited at most one time,
> and types are propagated from bottom to top. ExpressionVisitor may be
> called several times on nested nodes and will therefore re-explore some
> of them several times, thus re-creating types.
That's true, although I think you can write it with the expression visitor in 
such a way that this still holds. I will admit that that's not the case in 
Python currently, it has O(n²) complexity for some constructions ;) That could 
be fixed though, should it become a problem.
Determining the type of every node doesn't sound very useful on the other 
hand. What can this be used for? The information is discarded after the 
builder finishes anyways.

> * There is a clear separation between the creation of the types (when a
> new type is encountered, it is passed to ParseSession::setTypeOfNode)
> and the use of types (ParseSession::typeOfNode does never create a
> type). This may be important in order to avoid the code-completion code
> to create types where it had to reuse existing ones, but I've still to
> look closer at how you implemented that in the Python language plugin.
That's exactly what the expression visitor concept gives you, isn't it? One 
class instantiates the types, and another one stores them in the duchain.

> Yes, the biggest advantage of ExpressionVisitor is that it allows some
> sort of "look-ahead". You can compute the type of a variable before
> entering its node. My solution requires that the expression has been
> visited in order to have its type computed and stored, so you have to
> declare variables in endVisit() in order to be able to use
> m_session->typeOfNode(node->expression);
Yes, that's a good observation. While it has no theoretical advantage, I find 
it much easier to read (and debug!).

> The only problem that may arise is that I must create the empty context
> at the declaration of v, but I need to add imported contexts to it
> afterward. Is it possible to call DUContext::addImportedParentContext on
> a context that already has a parent? (I've read that I need to check
> TopDUContext::isInChain or something like that)
Yes, as far as I'm aware you can add parent contexts at any time.
The idea you described sounds clever, but I can't judge from my head if it 
would work or not. You would have to try it. ;)


More information about the KDevelop-devel mailing list