Hi, I'm trying to construct a call emission from what I suspect is a somewhat unconventional location in SILExpr.cpp. This is going to be a long, and somewhat unfocused set of questions, because I tried several approaches to get this working.
For context, what I'm trying to do is make something like this compile: \MyType.myFunction(arg: someArgument)
. In other words, I want to generalize KeyPath
s to accept function calls, too (and write a pitch for this feature once I have a prototype working). I have the parsing and type-checking done (I think), but I'm having a lot of trouble getting SIL generation to work.
Clearly, inside of RValueEmitter::visitKeyPathExpr
, I need to construct a closure that does the equivalent of the subscript version of this function. My understanding is that functions like getOrCreateKeyPathGetter
are making a closure that would basically look like this, if it was written in code for a subscript with one argument:
{ callee in
callee[arg: arg1]
}
I was originally expecting that a subscript is basically exactly like a function, and that some slight modifications to the subscript version would have this working. But it seems that that is not the case. I ran out of ideas when I got to the point where I needed to have a AbstractStorageDecl
; it didn't seem like a good idea to try to fake this, and the code using it didn't seem like it would be easy to modify to not need it.
My next attempt seemed more correct, and is also where CallEmission
first shows up. I tried to look at how "real" function call expressions are constructed, and to copy that. So, it seemed like I needed a CallEmission
to do this; and here, again, I ran into problems. I'm not sure how to make the self
call without some form of Call Expr. To my surprise, a Callee
seems to be a function, not an instance of some type (or the type itself for a static/class function), based on the code in CalleeTypeInfo::createCalleeTypeInfo
, specifically:
result.substFnType =
formalFnType.castTo<SILFunctionType>()->substGenericArgs(
SGF.SGM.M, Substitutions, SGF.getTypeExpansionContext());
For context: I constructed my callee using Callee::forIndirect
, and passed the ManagedValue
output from the prior KeyPath segment as my indirectValue
.
I have a few ideas for how to proceed from here, but they're all fairly labor intensive; most of them basically involve starting from the top of how a "normal" Swift function call is type checked and has SIL emitted. I figured at this point it was better to ask and see if there's something obvious I'm missing before I go down this road.
So what I'm looking for, is some general advice on whether this is the right approach, how to get it working, and maybe also some context around why Callee
is supposed to be a function and why subscripts seem so much easier to construct a call for in SIL than functions?
Thanks for reading!