-
Notifications
You must be signed in to change notification settings - Fork 244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IRFunctionRegistry changes #3202
IRFunctionRegistry changes #3202
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one tiny style comment
} | ||
|
||
def lookupFunction(name: String, args: Seq[Type]): Option[IRFunction] = { | ||
val validF = codeRegistry(name).flatMap { case (ts, f) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you use any fail all fail here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None of the things (except the return) are Options? I don't see how it would work here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh, got it. nevermind.
* separate IR conversions from IRFunction conversions in IRFunctionRegistry * change ApplyFunction(impl, args) => Apply(fn, args, impl) * cleanup
val registry: mutable.Map[String, Seq[(Seq[Type], Seq[IR] => IR)]] = mutable.Map().withDefaultValue(Seq.empty) | ||
val irRegistry: mutable.Map[String, Seq[(Seq[Type], Seq[IR] => IR)]] = mutable.Map().withDefaultValue(Seq.empty) | ||
|
||
val codeRegistry: mutable.Map[String, Seq[(Seq[Type], IRFunction)]] = mutable.Map().withDefaultValue(Seq.empty) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@catoverdrive Sorry I'm late to the game here. We should use mutable.MultiMap
when we have Map[K, Set[V]]
. Unless there's a compelling case for Seq
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That also makes addIRFunction
and addIR
just calls to irRegistry.addBinding
and codeRegistry.addBinding
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
womp, I didn't know this was a thing. I'll change.
} | ||
|
||
def lookupFunction(name: String, args: Seq[Type]): Option[Seq[IR] => IR] = { | ||
def lookupConversion(name: String, args: Seq[Type]): Option[Seq[IR] => IR] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lookupConversion
and lookupFunction
are suspiciously similar. I'm not sure I see the compelling reason to keep them separate.
Would the code look simpler if we had one MultiMap[String, IRFun]
where IRFun
was something like:
trait IRFun {
def args: Seq[Type]
def ret: Type
def emit(
emitter: IR => (Code[Unit], Code[Boolean], Code[_]),
mb: MethodBuilder,
args: IR*
): (Code[Unit], Code[Boolean], Code[_])
}
class IRMacro(
val args: Seq[Type],
val ret: Type,
val impl: Array[IR] => IR
) extends IRFun {
def emit(
emitter: IR => (Code[Unit], Code[Boolean], Code[_]),
mb: MethodBuilder,
args: IR*
): (Code[Unit], Code[Boolean], Code[_]) = emitter(impl(args.toArray))
}
class JVMFun(
val args: Seq[Type],
retType: Type,
impl: (MethodBuilder, Array[Code[_]]) => Code[_]
) extends IRFun {
def emit(
emitter: IR => (Code[Unit], Code[Boolean], Code[_]),
mb: MethodBuilder,
args: IR*
): (Code[Unit], Code[Boolean], Code[_]) = {
val (setup, ms, vs) = args.map(emitter).unzip
(Code(setup:_*), ms.fold(_ || _), impl(mb, vs))
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe let JVMFun also control missingness?
class MissingAwareJVMFun(
val args: Seq[Type],
retType: Type,
impl: (MethodBuilder, Array[Code[_]]) => (Code[Unit], Code[Boolean], Code[_])
) extends IRFun {
def emit(
emitter: IR => (Code[Unit], Code[Boolean], Code[_]),
mb: MethodBuilder,
args: IR*
): (Code[Unit], Code[Boolean], Code[_]) = {
val (setups, ms, vs) = args.map(emitter).unzip
val (setup, m, v) = impl(mb, vs)
(Code(setups ++ setup:_*), (ms :+ m).fold(_ || _), v)
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really want to entangle them because of two resasons:
- Things that can be translated directly (
Seq[IR] => IR
) are maybe things that we don't want to keep in the function registry once we can directly pass AST nodes from Python. I kind of want all of them to go away. - Even if we do want to keep them in the function registry, I want to be able to look up the non-IR conversions post optimization, when we go to compile the code. Once we're no longer translating from AST, we don't need to store the implementation as part of the IR node and can look it up after we're done optimizing the overall IR. I feel like the things that are implemented in terms of existing IR nodes should just go directly into the IR tree and optimized away with the rest of it. (this is kind of what currently happens;
Infer
onApply
nodes does a lookup on the IRFunction registry to be able to properly infer the return type)
* separate IR conversions from IRFunction conversions in IRFunctionRegistry * change ApplyFunction(impl, args) => Apply(fn, args, impl) * cleanup
* separate IR conversions from IRFunction conversions in IRFunctionRegistry * change ApplyFunction(impl, args) => Apply(fn, args, impl) * cleanup
cc @cseed @danking
I changed the
ApplyFunction
IR to store the function name instead of the IRFunction implementation. (The implementation gets looked up during Infer if it doesn't already exist, but we're always pre-populating it in IRFunctionRegistry.lookupConversion).As part of this, I separated the way that
IRFunctionRegistry
stores IR => IR from the IRFunction lookup, since the lookup in Infer wants to grab the IRFunction and not necessarily the entireApply
IR that we currently store. Maybe the IR => IR aspect (handled byIRFunction.lookupConversion
) could go away once we no longer need the AST to IR conversion and start constructing the IR directly in python.