Skip to content
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

Sum type info in suggestions DB #3422

Merged
merged 10 commits into from
May 5, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@
- [Fixed execution of defaulted arguments of Atom Constructors][3358]
- [Converting Enso Date to java.time.LocalDate and back][3374]
- [Functions with all-defaulted arguments now execute automatically][3414]
- [Provide `tagValues` for function arguments in the language server][3422]

[3227]: https://github.com/enso-org/enso/pull/3227
[3248]: https://github.com/enso-org/enso/pull/3248
Expand All @@ -198,6 +199,8 @@
[3412]: https://github.com/enso-org/enso/pull/3412
[3414]: https://github.com/enso-org/enso/pull/3414
[3417]: https://github.com/enso-org/enso/pull/3417
[3417]: https://github.com/enso-org/enso/pull/3417
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate link

[3422]: https://github.com/enso-org/enso/pull/3422

# Enso 2.0.0-alpha.18 (2021-10-12)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
}
],
"returnType" : "MyAtom",
Expand Down Expand Up @@ -141,14 +142,16 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "MyType",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "foo",
"reprType" : "Number",
"isSuspended" : false,
"hasDefault" : true,
"defaultValue" : "42"
"defaultValue" : "42",
"tagValues" : null
}
],
"selfType" : "MyType",
Expand Down Expand Up @@ -224,21 +227,24 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "b",
"reprType" : "Any",
"isSuspended" : true,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "c",
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : true,
"defaultValue" : "C"
"defaultValue" : "C",
"tagValues" : null
}
],
"returnType" : "IO",
Expand Down Expand Up @@ -356,21 +362,24 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "b",
"reprType" : "Any",
"isSuspended" : true,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "c",
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : true,
"defaultValue" : "C"
"defaultValue" : "C",
"tagValues" : null
}
],
"returnType" : "IO",
Expand Down Expand Up @@ -398,7 +407,8 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
}
],
"returnType" : "MyAtom",
Expand Down Expand Up @@ -461,14 +471,16 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "MyType",
"isSuspended" : false,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
},
{
"name" : "foo",
"reprType" : "Number",
"isSuspended" : false,
"hasDefault" : true,
"defaultValue" : "42"
"defaultValue" : "42",
"tagValues" : null
}
],
"selfType" : "MyType",
Expand Down Expand Up @@ -572,7 +584,8 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"reprType" : "Any",
"isSuspended" : true,
"hasDefault" : false,
"defaultValue" : null
"defaultValue" : null,
"tagValues" : null
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ object Suggestion {
reprType: String,
isSuspended: Boolean,
hasDefault: Boolean,
defaultValue: Option[String]
defaultValue: Option[String],
tagValues: Option[Seq[String]] = None
) extends ToLogString {

/** @inheritdoc */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ sealed trait Tree[+A] {
final def map[B](f: A => B): Tree[B] =
Tree.map(this)(f)

@JsonIgnore
final def collectFirst[B](f: PartialFunction[A, B]): Option[B] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some documentation

Tree.collectFirst(this)(f)

/** Selects all elements which satisfy a predicate.
*
* @param p the predicate used to test elements
Expand Down Expand Up @@ -208,6 +212,22 @@ object Tree {
Node(f(a), cx.map(mapNode(_)(f)))
}

private def collectFirst[A, B](
tree: Tree[A]
)(f: PartialFunction[A, B]): Option[B] = {
def collectFirstNode(node: Tree.Node[A]): Option[B] = {
if (f.isDefinedAt(node.element)) {
Some(f(node.element))
} else {
node.children.collectFirst((collectFirstNode _).unlift)
}
}
tree match {
case Root(c) => c.collectFirst((collectFirstNode _).unlift)
case n: Node[A] => collectFirstNode(n)
}
}

private def filter[A](tree: Tree[A])(p: A => Boolean): Tree[A] = {
def filterNode(node: Tree.Node[A]): Option[Tree.Node[A]] = {
val childrenFiltered = node.children.flatMap(filterNode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class RuntimeStubsGenerator() {
BindingAnalysis,
"Non-parsed module used in stubs generator"
)
localBindings.types.foreach { tp =>
localBindings.constructors.foreach { tp =>
val constructor = new AtomConstructor(tp.name, scope)
scope.registerConstructor(constructor)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,13 +336,22 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
resolvedName match {
case BindingsMap.ResolvedModule(module) =>
Some(module.getName)
case BindingsMap.ResolvedConstructor(module, cons) =>
Some(module.getName.createChild(cons.name))
case cons: BindingsMap.ResolvedConstructor =>
Some(cons.qualifiedName)
case _ =>
None
}
}

private def buildResolvedUnionTypeName(
resolvedName: BindingsMap.ResolvedTypeName
): Option[TypeArg] = resolvedName match {
case tp: BindingsMap.ResolvedType =>
Some(TypeArg.Sum(tp.qualifiedName, tp.getVariants.map(_.qualifiedName)))
case other: BindingsMap.ResolvedName =>
buildResolvedTypeName(other).map(TypeArg.Value)
}

/** Build type signature from the ir metadata.
*
* @param typeSignature the type signature metadata
Expand Down Expand Up @@ -380,19 +389,18 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
args :++ arg
case IR.Function.Lambda(List(targ), body, _, _, _, _) =>
val typeName = targ.name.name
val qualifiedTypeName = resolveTypeName(bindings, typeName)
.getOrElse(QualifiedName.simpleName(typeName))
val tdef = TypeArg.Value(qualifiedTypeName)
val tdef = resolveTypeName(bindings, typeName)
.getOrElse(TypeArg.Value(QualifiedName.simpleName(typeName)))
go(body, args :+ tdef)
case IR.Application.Prefix(tfun, targs, _, _, _, _) =>
val appFunction = go(tfun, Vector()).head
val appArgs = targs.flatMap(arg => go(arg.value, Vector()))
args :+ TypeArg.Application(appFunction, appArgs.toVector)
case tname: IR.Name =>
val typeName = tname.name
val qualifiedTypeName = resolveTypeName(bindings, typeName)
.getOrElse(QualifiedName.simpleName(typeName))
args :+ TypeArg.Value(qualifiedTypeName)
val tdef = resolveTypeName(bindings, typeName)
.getOrElse(TypeArg.Value(QualifiedName.simpleName(typeName)))
args :+ tdef
case _ =>
args
}
Expand All @@ -415,10 +423,10 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
private def resolveTypeName(
bindings: Option[BindingAnalysis.Metadata],
name: String
): Option[QualifiedName] = {
): Option[TypeArg] = {
bindings
.flatMap(_.resolveUppercaseName(name).toOption)
.flatMap(buildResolvedTypeName)
.flatMap(_.resolveTypeName(name).toOption)
.flatMap(buildResolvedUnionTypeName)
}

/** Build arguments of a method.
Expand Down Expand Up @@ -521,7 +529,11 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
reprType = buildTypeArgumentName(targ),
isSuspended = varg.suspended,
hasDefault = varg.defaultValue.isDefined,
defaultValue = varg.defaultValue.flatMap(buildDefaultValue)
defaultValue = varg.defaultValue.flatMap(buildDefaultValue),
tagValues = targ match {
case TypeArg.Sum(_, variants) => Some(variants.map(_.toString))
case _ => None
}
)

/** Build the name of type argument.
Expand Down Expand Up @@ -549,6 +561,7 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
val argsList = args.map(go(_, level + 1)).mkString(" ")
val typeName = s"$funText $argsList"
if (level > 0) s"($typeName)" else typeName
case TypeArg.Sum(n, _) => n.toString
}

go(targ, 0)
Expand Down Expand Up @@ -639,6 +652,9 @@ object SuggestionBuilder {
sealed private trait TypeArg
private object TypeArg {

case class Sum(name: QualifiedName, variants: Seq[QualifiedName])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentation

extends TypeArg

/** Type with the name, like `A`.
*
* @param name the name of the type
Expand Down
99 changes: 99 additions & 0 deletions engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,105 @@ object IR {
}
object Definition {

/** The definition of a union type and its members.
*
* NB: this should probably be removed once we propagate the union
* types logic through the runtime and implement statics – the whole
* notion of desugaring complex type definitions becomes obsolete then.
*
* @param name the name of the union
* @param members the members of this union
* @param location the source location that the node corresponds to
* @param passData the pass metadata associated with this node
* @param diagnostics compiler diagnostics for this node
*/
sealed case class UnionType(
name: IR.Name,
members: List[IR.Name],
override val location: Option[IdentifiedLocation],
override val passData: MetadataStorage = MetadataStorage(),
override val diagnostics: DiagnosticStorage = DiagnosticStorage()
) extends Definition
with IRKind.Primitive {
override protected var id: Identifier = randomId

def copy(
name: IR.Name = name,
members: List[IR.Name] = members,
location: Option[IdentifiedLocation] = location,
passData: MetadataStorage = passData,
diagnostics: DiagnosticStorage = diagnostics,
id: Identifier = id
): UnionType = {
val res = UnionType(name, members, location, passData, diagnostics)
res.id = id
res
}

/** @inheritdoc */
override def duplicate(
keepLocations: Boolean = true,
keepMetadata: Boolean = true,
keepDiagnostics: Boolean = true,
keepIdentifiers: Boolean = false
): UnionType =
copy(
name = name.duplicate(
keepLocations,
keepMetadata,
keepDiagnostics,
keepIdentifiers
),
members = members.map(
_.duplicate(
keepLocations,
keepMetadata,
keepDiagnostics,
keepIdentifiers
)
),
location = if (keepLocations) location else None,
passData =
if (keepMetadata) passData.duplicate else MetadataStorage(),
diagnostics =
if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(),
id = if (keepIdentifiers) id else randomId
)

/** @inheritdoc */
override def setLocation(
location: Option[IdentifiedLocation]
): UnionType =
copy(location = location)

/** @inheritdoc */
override def mapExpressions(fn: Expression => Expression): UnionType =
this

/** @inheritdoc */
override def toString: String =
s"""
|IR.Module.Scope.Definition.UnionType(
|name = $name,
|members = $members,
|location = $location,
|passData = ${this.showPassData},
|diagnostics = $diagnostics,
|id = $id
|)
|""".toSingleLine

/** @inheritdoc */
override def children: List[IR] = name :: members

/** @inheritdoc */
override def showCode(indent: Int): String = {
val fields = members.map(_.showCode(indent)).mkString(" | ")

s"type ${name.showCode(indent)} = $fields"
}
}

/** The definition of an atom constructor and its associated arguments.
*
* @param name the name of the atom
Expand Down
Loading