During normal compilation models are evaluated/expanded during parsing and afterwards all references to them are pruned out of the AST.
During development it would be nice if the LSP could provide also help inside models.
However as far as I can see this is really hard because models depend highly on the context they are used.
For example:
model abc(): Ex = {
baum + 1
}
There is nothing we can say for certain about the body of this model. The type of the expression is completely dependend on the context it is called on and what baum binds to.
Idea 0: Ignore model bodies
This is what we currently do, and for normal compilation what we want since there is nothing to be gained from analysing them
Update: In the meeting today (2026-06-08) we figured out that the LSP uses the values from the first invocation.
Idea 1: Island model
Since we don't know the context of the models we could always treat them as independent islands without any context.
Obviously in many cases like the example above this would not help since we still don't know what baum refers to but in some other cases it could help.
model abc(): Defs = {
constant apfel = 3 as Bits<8>
constant strudel = let teig = 6 in apfel + teig
}
Like here all the necessary context to provide goto definitions and type information and signature information is contained inside the model and could work.
To be fair this is quite a bit of work, especially for someone who new to the frontend, because we now have to symbol resolve and typecheck code where we have to assume that it might not be valid code and we still cannot report any errors for the macro bodies.
Idea 2: Analyse all macro call sites.
I think you maybe could analyse all macro call sites and if they are all in the same scope or have some common ancestor this could be used as a scope.
Obviously this would provide the best results but it is also the hardest implementation and I'm not yet sure how this would be implemented.
This is hardent because the Symbol resolver doesn't really implement multiple ancestors but instead manges them with a hack (by copying all symbols in one scope into the current scope, emulating multiple ancestry.
Also if another file imports the macro you need to be aware of that, because that could minimize the common ancestor logic.
During normal compilation models are evaluated/expanded during parsing and afterwards all references to them are pruned out of the AST.
During development it would be nice if the LSP could provide also help inside models.
However as far as I can see this is really hard because models depend highly on the context they are used.
For example:
There is nothing we can say for certain about the body of this model. The type of the expression is completely dependend on the context it is called on and what
baumbinds to.Idea 0: Ignore model bodies
This is what we currently do, and for normal compilation what we want since there is nothing to be gained from analysing themUpdate: In the meeting today (2026-06-08) we figured out that the LSP uses the values from the first invocation.
Idea 1: Island model
Since we don't know the context of the models we could always treat them as independent islands without any context.
Obviously in many cases like the example above this would not help since we still don't know what
baumrefers to but in some other cases it could help.Like here all the necessary context to provide goto definitions and type information and signature information is contained inside the model and could work.
To be fair this is quite a bit of work, especially for someone who new to the frontend, because we now have to symbol resolve and typecheck code where we have to assume that it might not be valid code and we still cannot report any errors for the macro bodies.
Idea 2: Analyse all macro call sites.
I think you maybe could analyse all macro call sites and if they are all in the same scope or have some common ancestor this could be used as a scope.
Obviously this would provide the best results but it is also the hardest implementation and I'm not yet sure how this would be implemented.
This is hardent because the Symbol resolver doesn't really implement multiple ancestors but instead manges them with a hack (by copying all symbols in one scope into the current scope, emulating multiple ancestry.
Also if another file imports the macro you need to be aware of that, because that could minimize the common ancestor logic.