Skip to content

Commit

Permalink
Static, but instance, but static (#3764)
Browse files Browse the repository at this point in the history
Adds the ability to write `Foo.method (Mk_Foo 123)` as a synonym of `(Mk_Foo 123).method` because Rust.
kustosz authored Oct 10, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 7e0ab89 commit b3dd778
Showing 7 changed files with 76 additions and 17 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -378,6 +378,7 @@
- [Invalidate module's IR cache if imported module changed][3703]
- [Don't rename imported Main module that only imports names][3710]
- [Notify node status to the IDE][3729]
- [Make instance methods callable like statics][3764]
- [Distinguish static and instance methods][3740]
- [By-type pattern matching][3742]
- [Fix performance of method calls on polyglot arrays][3781]
@@ -431,6 +432,7 @@
[3710]: https://github.com/enso-org/enso/pull/3710
[3729]: https://github.com/enso-org/enso/pull/3729
[3740]: https://github.com/enso-org/enso/pull/3740
[3764]: https://github.com/enso-org/enso/pull/3764
[3742]: https://github.com/enso-org/enso/pull/3742
[3781]: https://github.com/enso-org/enso/pull/3781

Original file line number Diff line number Diff line change
@@ -1474,7 +1474,11 @@ class IrToTruffle(

val argName = arg.getName

if (seenArgNames contains argName) {
if (
argName != Constants.Names.SELF_ARGUMENT && seenArgNames.contains(
argName
)
) {
throw new IllegalStateException(
s"A duplicate argument name, $argName, was found during codegen."
)
Original file line number Diff line number Diff line change
@@ -74,14 +74,14 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {

go(tree ++= tpSuggestions.map(Tree.Node(_, Vector())), scope)

case IR.Module.Scope.Definition.Method
case m @ IR.Module.Scope.Definition.Method
.Explicit(
IR.Name.MethodReference(typePtr, methodName, _, _, _),
IR.Function.Lambda(args, body, _, _, _, _),
_,
_,
_
) =>
) if !m.isStaticWrapperForInstanceMethod =>
val typeSignature = ir.getMetadata(TypeSignatures)
val selfTypeOpt = typePtr match {
case Some(typePtr) =>
15 changes: 15 additions & 0 deletions engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala
Original file line number Diff line number Diff line change
@@ -1455,6 +1455,21 @@ object IR {
true // if it's not a function, it has no arguments, therefore no `self`
}

def isStaticWrapperForInstanceMethod: Boolean = body match {
case function: Function.Lambda =>
function.arguments.map(_.name) match {
case IR.Name.Self(_, true, _, _) :: IR.Name.Self(
_,
false,
_,
_
) :: _ =>
true
case _ => false
}
case _ => false
}

}

/** The definition of a method for a given constructor using sugared
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import org.enso.compiler.context.{InlineContext, ModuleContext}
import org.enso.compiler.core.IR
import org.enso.compiler.core.ir.MetadataStorage.ToPair
import org.enso.compiler.data.BindingsMap
import org.enso.compiler.data.BindingsMap.{Resolution, ResolvedType}
import org.enso.compiler.exception.CompilerError
import org.enso.compiler.pass.IRPass
import org.enso.compiler.pass.analyse.BindingAnalysis
@@ -84,7 +85,38 @@ case object MethodDefinitions extends IRPass {
case other => other
}

ir.copy(bindings = newDefs)
val withStaticAliases = newDefs.flatMap {
case method: IR.Module.Scope.Definition.Method.Explicit
if !method.isStatic =>
method.methodReference.typePointer.flatMap(
_.getMetadata(this)
) match {
case Some(Resolution(ResolvedType(_, tp))) if tp.members.nonEmpty =>
val dup = method.duplicate()
val static = dup.copy(body =
IR.Function.Lambda(
List(
IR.DefinitionArgument
.Specified(
IR.Name.Self(None, true),
None,
None,
false,
None
)
),
dup.body,
None
)
)
List(method, static)
case _ => List(method)
}

case other => List(other)
}

ir.copy(bindings = withStaticAliases)
}

private def resolveType(
Original file line number Diff line number Diff line change
@@ -47,8 +47,8 @@ case object OverloadsResolution extends IRPass {
ir: IR.Module,
@unused moduleContext: ModuleContext
): IR.Module = {
var seenTypes: Set[String] = Set()
var seenMethods: Map[Option[String], Set[String]] = Map()
var seenTypes: Set[String] = Set()
var seenMethods: Map[Option[String], Set[(String, Boolean)]] = Map()

val types = ir.bindings.collect {
case tp: IR.Module.Scope.Definition.Type => tp
@@ -72,7 +72,7 @@ case object OverloadsResolution extends IRPass {
val newMethods: List[IR.Module.Scope.Definition] = methods.map(method => {
if (
seenMethods(method.typeName.map(_.name))
.contains(method.methodName.name)
.contains((method.methodName.name, method.isStatic))
) {
IR.Error.Redefined
.Method(method.typeName, method.methodName, method.location)
@@ -85,10 +85,10 @@ case object OverloadsResolution extends IRPass {
method.location
)
case _ =>
val currentMethods = seenMethods(method.typeName.map(_.name))
val currentMethods: Set[(String, Boolean)] =
seenMethods(method.typeName.map(_.name))
seenMethods = seenMethods + (method.typeName.map(_.name) ->
(currentMethods + method.methodName.name))

(currentMethods + ((method.methodName.name, method.isStatic))))
method
}
}
Original file line number Diff line number Diff line change
@@ -165,19 +165,25 @@ class MethodsTest extends InterpreterTest {
eval(code).toString shouldEqual "(Mk_Foo 123)"
}

"not be callable on types when non-static" in {
"be callable on types when non-static, with additional self arg" in {
val code =
"""
"""from Standard.Base.IO import all
|
|type Foo
| Mk_Foo a
|
| inc self = Mk_Foo self.a
| inc self = Foo.Mk_Foo self.a+1
|
|main = Foo.inc
|main =
| IO.println (Foo.inc (Foo.Mk_Foo 12))
| IO.println (Foo.Mk_Foo 13).inc
| IO.println (.inc self=Foo self=(Foo.Mk_Foo 14))
| IO.println (Foo.inc self=(Foo.Mk_Foo 15))
|""".stripMargin
the[InterpreterException] thrownBy eval(
code
) should have message "Method `inc` of Foo could not be found."
eval(code)
consumeOut.shouldEqual(
List("(Mk_Foo 13)", "(Mk_Foo 14)", "(Mk_Foo 15)", "(Mk_Foo 16)")
)
}

"not be callable on instances when static" in {

0 comments on commit b3dd778

Please sign in to comment.