mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 21:12:44 +03:00
Add smart constructors for the core nodes (#480)
This commit is contained in:
parent
a288ecaa5c
commit
9dee1911f8
10
build.sbt
10
build.sbt
@ -312,6 +312,9 @@ lazy val graph = (project in file("common/graph/"))
|
||||
"com.github.ghik" % "silencer-lib" % silencerVersion % Provided cross CrossVersion.full
|
||||
),
|
||||
addCompilerPlugin(
|
||||
"org.typelevel" %% "kind-projector" % "0.11.0" cross CrossVersion.full
|
||||
),
|
||||
addCompilerPlugin (
|
||||
"org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full
|
||||
),
|
||||
addCompilerPlugin("io.tryp" % "splain" % "0.5.0" cross CrossVersion.patch),
|
||||
@ -394,6 +397,9 @@ lazy val core_definition = (project in file("engine/core-definition"))
|
||||
addCompilerPlugin(
|
||||
"org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full
|
||||
),
|
||||
addCompilerPlugin(
|
||||
"org.typelevel" %% "kind-projector" % "0.11.0" cross CrossVersion.full
|
||||
),
|
||||
addCompilerPlugin("io.tryp" % "splain" % "0.5.0" cross CrossVersion.patch),
|
||||
scalacOptions ++= Seq(
|
||||
"-P:splain:infix:true",
|
||||
@ -403,6 +409,7 @@ lazy val core_definition = (project in file("engine/core-definition"))
|
||||
)
|
||||
)
|
||||
.dependsOn(graph)
|
||||
.dependsOn(syntax.jvm)
|
||||
|
||||
lazy val runtime = (project in file("engine/runtime"))
|
||||
.configs(Benchmark)
|
||||
@ -444,6 +451,9 @@ lazy val runtime = (project in file("engine/runtime"))
|
||||
addCompilerPlugin(
|
||||
"org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full
|
||||
),
|
||||
addCompilerPlugin(
|
||||
"org.typelevel" %% "kind-projector" % "0.11.0" cross CrossVersion.full
|
||||
),
|
||||
addCompilerPlugin("io.tryp" % "splain" % "0.5.0" cross CrossVersion.patch),
|
||||
scalacOptions ++= Seq(
|
||||
"-P:splain:infix:true",
|
||||
|
@ -19,6 +19,8 @@ import shapeless.nat._
|
||||
* as much as possible.
|
||||
* - Basic equality testing (that should be overridden as needed).
|
||||
* - An ability to define fields that store complex data such as `String`.
|
||||
* - Add a `Default` typeclass, and ensure that all component fields are
|
||||
* instances of it. Fields should then be initialised using it.
|
||||
*/
|
||||
|
||||
/** This file contains the implementation of an incredibly generic graph.
|
||||
@ -357,8 +359,6 @@ object Graph {
|
||||
@newtype
|
||||
final case class Ref[G <: Graph, C <: Component](ix: Int)
|
||||
|
||||
// === Refined ===
|
||||
|
||||
/** Type refinement for component references.
|
||||
*
|
||||
* Type refinement is used to add additional information to a [[Component]]
|
||||
@ -370,11 +370,14 @@ object Graph {
|
||||
* encoded having the following type `Refined[Shape, App, Node]`.
|
||||
*/
|
||||
@newtype
|
||||
final case class Refined[C <: Component.Field, Spec, T](wrapped: T)
|
||||
final case class Refined[F <: Component.Field, Spec, T](wrapped: T)
|
||||
object Refined {
|
||||
implicit def unwrap[C <: Component.Field, S, T](
|
||||
t: Refined[C, S, T]
|
||||
implicit def unwrap[F <: Component.Field, S <: F, T](
|
||||
t: Refined[F, S, T]
|
||||
): T = { t.wrapped }
|
||||
|
||||
def wrap[F <: Component.Field, S <: F, T](t: T): Refined[F, S, T] =
|
||||
Refined(t)
|
||||
}
|
||||
|
||||
// === List ===
|
||||
@ -721,7 +724,8 @@ object Graph {
|
||||
ev3: HListTakeUntil.Aux[C, ComponentList, PrevComponentList],
|
||||
ev4: hlist.Length.Aux[PrevComponentList, ComponentIndex],
|
||||
componentIndexEv: nat.ToInt[ComponentIndex],
|
||||
componentSizeEv: KnownSize[FieldList]
|
||||
componentSizeEv: KnownSize[FieldList],
|
||||
listContainsComponent: Selector[ComponentList, C]
|
||||
): HasComponent[G, C] = new HasComponent[G, C] {
|
||||
val componentIndex = componentIndexEv()
|
||||
val componentSize = componentSizeEv.asInt
|
||||
@ -751,7 +755,8 @@ object Graph {
|
||||
implicit
|
||||
ev1: Component.Field.List.Aux[G, C, FieldList],
|
||||
evx: HasComponent[G, C],
|
||||
fieldOffsetEv: SizeUntil[F, FieldList]
|
||||
fieldOffsetEv: SizeUntil[F, FieldList],
|
||||
containsField: Selector[FieldList, F]
|
||||
): HasComponentField[G, C, F] = new HasComponentField[G, C, F] {
|
||||
val componentIndex = evx.componentIndex
|
||||
val componentSize = evx.componentSize
|
||||
@ -783,4 +788,76 @@ object Graph {
|
||||
val sizes = info.componentSize +: tail.sizes
|
||||
}
|
||||
}
|
||||
|
||||
/** Allows casting between variant cases without actually mutating the
|
||||
* underlying structure.
|
||||
*
|
||||
* This is a very unsafe operation and should be used with care.
|
||||
*
|
||||
* @param component the component to cast the variant field in
|
||||
* @param ev evidence that component [[C]] has field [[G]] in graph [[G]]
|
||||
* @tparam G the graph type
|
||||
* @tparam C the component type
|
||||
* @tparam F the field type
|
||||
*/
|
||||
implicit class VariantCast[
|
||||
G <: Graph,
|
||||
C <: Component,
|
||||
F <: Component.Field
|
||||
](val component: Component.Ref[G, C])(
|
||||
implicit ev: HasComponentField[G, C, F],
|
||||
graph: GraphData[G]
|
||||
) {
|
||||
|
||||
/** Checks if [[component]] is in the variant case denoted by the type
|
||||
* [[V]].
|
||||
*
|
||||
* @param variantIndexed information that [[F]] is indeed a variant, with
|
||||
* [[V]] as a valid case
|
||||
* @tparam V the type of the variant case in question
|
||||
* @return `true` if [[component]] is of the form denoted by [[V]], `false`
|
||||
* otherwise
|
||||
*/
|
||||
def is[V <: F](
|
||||
implicit variantIndexed: VariantIndexed[F, V]
|
||||
): Boolean = {
|
||||
graph.unsafeReadField[C, F](component) == variantIndexed.ix
|
||||
}
|
||||
|
||||
/** Casts the variant field [[F]] to behave as the variant branch [[V]].
|
||||
*
|
||||
* It should be noted that this is purely a superficial cast, and does not
|
||||
* affect the underlying graph. This means that [[C]] will still pattern
|
||||
* match as if it was its original variant branch.
|
||||
*
|
||||
* @param variantIndexed information that [[F]] is indeed a variant, with
|
||||
* [[V]] as a valid case
|
||||
* @tparam V the type of the variant case in question
|
||||
* @return the component [[component]] refined to be the variant branch
|
||||
* [[V]]
|
||||
*/
|
||||
def unsafeAs[V <: F](
|
||||
implicit variantIndexed: VariantIndexed[F, V]
|
||||
): Component.Refined[F, V, Component.Ref[G, C]] = {
|
||||
Component.Refined[F, V, Component.Ref[G, C]](component)
|
||||
}
|
||||
|
||||
/** Performs a checked cast of [[component]] to the variant state denoted
|
||||
* by [[V]].
|
||||
*
|
||||
* @param variantIndexed information that [[F]] is indeed a variant, with
|
||||
* [[V]] as a valid case
|
||||
* @tparam V the type of the variant case in question
|
||||
* @return [[Some]] if [[component]] is a [[V]], otherwise [[None]]
|
||||
*/
|
||||
def as[V <: F](
|
||||
implicit variantIndexed: VariantIndexed[F, V]
|
||||
): Option[Component.Refined[F, V, Component.Ref[G, C]]] = {
|
||||
if (is[V]) {
|
||||
Some(unsafeAs[V])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +230,11 @@ object Macro {
|
||||
}
|
||||
}
|
||||
|
||||
/** Generates a getter for an element of a non-variant field.
|
||||
/** Generates a getter for an element of a field.
|
||||
*
|
||||
* In the case where the field is _not_ simple, the subfield offsets are
|
||||
* all incremented by one, to account for the fact that the first index
|
||||
* in a non-simple (variant) field encodes the variant branch.
|
||||
*
|
||||
* @param paramDef the definition of the subfield
|
||||
* @param enclosingTypeName the name of the field type
|
||||
@ -277,7 +281,7 @@ object Macro {
|
||||
$graphTermName.Component.Ref(
|
||||
graph.unsafeReadFieldByIndex[C, $enclosingTypeName](
|
||||
$graphTermName.Component.Refined.unwrap(node),
|
||||
$index
|
||||
${index + 1}
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -334,7 +338,7 @@ object Macro {
|
||||
$graphTermName.Component.Ref(
|
||||
graph.unsafeReadFieldByIndex[C, $enclosingTypeName](
|
||||
$graphTermName.Component.Refined.unwrap(node).ix,
|
||||
$index
|
||||
${index + 1}
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -343,7 +347,11 @@ object Macro {
|
||||
}
|
||||
}
|
||||
|
||||
/** Generates a setter for an element of a non-variant field.
|
||||
/** Generates a setter for an element of field.
|
||||
*
|
||||
* In the case where the field is _not_ simple, the subfield offsets are
|
||||
* all incremented by one, to account for the fact that the first index
|
||||
* in a non-simple (variant) field encodes the variant branch.
|
||||
*
|
||||
* @param paramDef the definition of the subfield
|
||||
* @param enclosingTypeName the name of the field type
|
||||
@ -388,7 +396,7 @@ object Macro {
|
||||
): Unit = {
|
||||
graph.unsafeWriteFieldByIndex[C, $enclosingTypeName](
|
||||
$graphTermName.Component.Refined.unwrap(node).ix,
|
||||
$index,
|
||||
${index + 1},
|
||||
value
|
||||
)
|
||||
}
|
||||
@ -441,7 +449,7 @@ object Macro {
|
||||
): Unit = {
|
||||
graph.unsafeWriteFieldByIndex[C, $enclosingTypeName](
|
||||
$graphTermName.Component.Refined.unwrap(node).ix,
|
||||
$index,
|
||||
${index + 1},
|
||||
value.ix
|
||||
)
|
||||
}
|
||||
@ -459,12 +467,6 @@ object Macro {
|
||||
*/
|
||||
def makeTypeAccessorName(fieldName: TypeName): String = {
|
||||
StringUtils.uncapitalize(fieldName.toString)
|
||||
// val matcher = "([A-Z])(.*)".r
|
||||
//
|
||||
// matcher.findFirstMatchIn(fieldName.toString) match {
|
||||
// case Some(t) => s"${t.group(1).toLowerCase()}${t.group(2)}"
|
||||
// case None => fieldName.toString.toLowerCase
|
||||
// }
|
||||
}
|
||||
|
||||
/** Generates accessor methods for the 'value class', the one that can
|
||||
@ -527,7 +529,7 @@ object Macro {
|
||||
}
|
||||
|
||||
/** Determines whether the parameter definition is defining an opaque
|
||||
* type. An opaque type is one not stored in the graph represntation.
|
||||
* type. An opaque type is one not stored in the graph representation.
|
||||
*
|
||||
* @param paramDef the definition to check
|
||||
* @return `true` if `paramDef` defines an opauqe type, otherwise `false`
|
||||
|
@ -95,7 +95,7 @@ class GraphTest extends FlatSpec with Matchers {
|
||||
case GraphImpl.Node.Shape.App.any(n1) => n1.fn
|
||||
}
|
||||
|
||||
refinedResult shouldEqual 1
|
||||
refinedResult shouldEqual 0
|
||||
}
|
||||
|
||||
"Component fields" can "be accessed properly" in {
|
||||
|
@ -173,9 +173,9 @@ object GraphTestDefinition {
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Edge[G] =
|
||||
// PrimGraph.Component.Ref(
|
||||
// graph.primUnsafeReadField[C, Shape](
|
||||
// graph.primUnsafeReadFieldByIndex[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 0
|
||||
// 1
|
||||
// )
|
||||
// )
|
||||
//
|
||||
@ -183,9 +183,9 @@ object GraphTestDefinition {
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Unit =
|
||||
// graph.primUnsafeWriteField[C, Shape](
|
||||
// graph.primUnsafeWriteFieldByIndex[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 0,
|
||||
// 1,
|
||||
// value.ix
|
||||
// )
|
||||
//
|
||||
@ -194,9 +194,9 @@ object GraphTestDefinition {
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Edge[G] =
|
||||
// PrimGraph.Component.Ref(
|
||||
// graph.primUnsafeReadField[C, Shape](
|
||||
// graph.primUnsafeReadFieldByIndex[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 1
|
||||
// 2
|
||||
// )
|
||||
// )
|
||||
//
|
||||
@ -204,9 +204,9 @@ object GraphTestDefinition {
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Unit =
|
||||
// graph.primUnsafeWriteField[C, Shape](
|
||||
// graph.primUnsafeWriteFieldByIndex[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 1,
|
||||
// 2,
|
||||
// value.ix
|
||||
// )
|
||||
//
|
||||
@ -265,9 +265,9 @@ object GraphTestDefinition {
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Edge[G] =
|
||||
// PrimGraph.Component.Ref(
|
||||
// graph.primUnsafeReadField[C, Shape](
|
||||
// graph.primUnsafeReadFieldByIndex[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 0
|
||||
// 1
|
||||
// )
|
||||
// )
|
||||
//
|
||||
@ -275,9 +275,9 @@ object GraphTestDefinition {
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Unit =
|
||||
// graph.primUnsafeWriteField[C, Shape](
|
||||
// graph.primUnsafeWriteFieldByIndex[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 0,
|
||||
// 2,
|
||||
// value.ix
|
||||
// )
|
||||
//
|
||||
@ -286,11 +286,7 @@ object GraphTestDefinition {
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): CentreVal[G] = {
|
||||
// CentreVal(
|
||||
// PrimGraph.Component.Ref(
|
||||
// graph.primUnsafeReadField[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 0
|
||||
// )
|
||||
// this.fn
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
@ -299,11 +295,7 @@ object GraphTestDefinition {
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Unit = {
|
||||
// graph.primUnsafeWriteField[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 0,
|
||||
// value.fn.ix
|
||||
// )
|
||||
// this.fn = value.fn
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@ -362,9 +354,9 @@ object GraphTestDefinition {
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Edge[G] = {
|
||||
// PrimGraph.Component.Ref(
|
||||
// graph.primUnsafeReadField[C, Shape](
|
||||
// graph.primUnsafeReadFieldByIndex[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 0 // as the other field is opaque
|
||||
// 1 // as the other field is opaque
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
@ -373,9 +365,9 @@ object GraphTestDefinition {
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Unit = {
|
||||
// graph.primUnsafeWriteField[C, Shape](
|
||||
// graph.primUnsafeWriteFieldByIndex[C, Shape](
|
||||
// PrimGraph.Component.Refined.unwrap(node).ix,
|
||||
// 0,
|
||||
// 1,
|
||||
// value.ix
|
||||
// )
|
||||
// }
|
||||
@ -422,7 +414,7 @@ object GraphTestDefinition {
|
||||
// ev: PrimGraph.HasComponentField[G, C, ParentLink]
|
||||
// ): Edge[G] = {
|
||||
// PrimGraph.Component.Ref(
|
||||
// graph.unsafeReadField[C, ParentLink](node.ix, 0)
|
||||
// graph.unsafeReadFieldByIndex[C, ParentLink](node.ix, 0)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
@ -430,7 +422,7 @@ object GraphTestDefinition {
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, ParentLink]
|
||||
// ): Unit = {
|
||||
// graph.unsafeWriteField[C, ParentLink](node.ix, 0, value.ix)
|
||||
// graph.unsafeWriteFieldByIndex[C, ParentLink](node.ix, 0, value.ix)
|
||||
// }
|
||||
//
|
||||
// def parentLink(
|
||||
@ -480,18 +472,18 @@ object GraphTestDefinition {
|
||||
// def line_=(value: Int)(
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Location]
|
||||
// ): Unit = graph.unsafeWriteField[C, Location](node.ix, 0, value)
|
||||
// ): Unit = graph.unsafeWriteFieldByIndex[C, Location](node.ix, 0, value)
|
||||
//
|
||||
// def column(
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Location]
|
||||
// ): Int =
|
||||
// graph.unsafeReadField[C, Location](node.ix, 1)
|
||||
// graph.unsafeReadFieldByIndex[C, Location](node.ix, 1)
|
||||
//
|
||||
// def column_=(value: Int)(
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Location]
|
||||
// ): Unit = graph.unsafeWriteField[C, Location](node.ix, 1, value)
|
||||
// ): Unit = graph.unsafeWriteFieldByIndex[C, Location](node.ix, 1, value)
|
||||
//
|
||||
// def location(
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
@ -593,26 +585,28 @@ object GraphTestDefinition {
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Node[G] =
|
||||
// PrimGraph.Component.Ref(
|
||||
// graph.unsafeReadField[C, Shape](node.ix, 0)
|
||||
// graph.unsafeReadFieldByIndex[C, Shape](node.ix, 0)
|
||||
// )
|
||||
//
|
||||
// def source_=(value: Node[G])(
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Unit = graph.unsafeWriteField[C, Shape](node.ix, 0, value.ix)
|
||||
// ): Unit =
|
||||
// graph.unsafeWriteFieldByIndex[C, Shape](node.ix, 0, value.ix)
|
||||
//
|
||||
// def target(
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Node[G] =
|
||||
// PrimGraph.Component.Ref(
|
||||
// graph.unsafeReadField[C, Shape](node.ix, 1)
|
||||
// graph.unsafeReadFieldByIndex[C, Shape](node.ix, 1)
|
||||
// )
|
||||
//
|
||||
// def target_=(value: Node[G])(
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
// ev: PrimGraph.HasComponentField[G, C, Shape]
|
||||
// ): Unit = graph.unsafeWriteField[C, Shape](node.ix, 1, value.ix)
|
||||
// ): Unit =
|
||||
// graph.unsafeWriteFieldByIndex[C, Shape](node.ix, 1, value.ix)
|
||||
//
|
||||
// def shape(
|
||||
// implicit graph: PrimGraph.GraphData[G],
|
||||
|
@ -18,7 +18,6 @@ class DocParserTests extends FlatSpec with Matchers {
|
||||
val output = DocParser.run(input)
|
||||
output match {
|
||||
case Result(_, Result.Success(value)) =>
|
||||
pprint.pprintln(value)
|
||||
assert(value == result)
|
||||
assert(value.show() == new Reader(input).toString())
|
||||
case _ =>
|
||||
|
@ -3,8 +3,8 @@ package org.enso.core
|
||||
import org.enso.graph.definition.Macro.{component, field, genGraph, opaque}
|
||||
import org.enso.graph.{Sized, VariantIndexed, Graph => PrimGraph}
|
||||
import shapeless.{::, HNil}
|
||||
import org.enso.syntax.text.AST
|
||||
|
||||
// TODO [AA] More detailed semantic descriptions for each node shape in future.
|
||||
object CoreGraph {
|
||||
@genGraph object Definition {
|
||||
|
||||
@ -38,6 +38,9 @@ object CoreGraph {
|
||||
*/
|
||||
@opaque case class Parent(opaque: Vector[Int])
|
||||
|
||||
/** Storage for raw AST nodes. */
|
||||
@opaque case class Ast(opaque: AST)
|
||||
|
||||
// ========================================================================
|
||||
// === Node ===============================================================
|
||||
// ========================================================================
|
||||
@ -176,7 +179,7 @@ object CoreGraph {
|
||||
/** An import statement.
|
||||
*
|
||||
* @param segments the segments of the import path, represented as a
|
||||
* [[NameLiteral]].
|
||||
* [[MetaList]].
|
||||
*/
|
||||
case class Import(segments: Link[G])
|
||||
|
||||
@ -199,7 +202,8 @@ object CoreGraph {
|
||||
/** An expanded-form type definition, with a body.
|
||||
*
|
||||
* @param name the name of the aggregate type
|
||||
* @param typeParams the type parameters to the definition
|
||||
* @param typeParams the type parameters to the definition, as a
|
||||
* [[MetaList]] of bindings
|
||||
* @param body the body of the type definition, represented as a
|
||||
* [[MetaList]] of bindings
|
||||
*/
|
||||
@ -211,7 +215,7 @@ object CoreGraph {
|
||||
|
||||
// === Typing =========================================================
|
||||
|
||||
/** A type signature.
|
||||
/** The ascription of a type to a value.
|
||||
*
|
||||
* @param typed the expression being ascribed a type
|
||||
* @param sig the signature being ascribed to [[typed]]
|
||||
@ -446,7 +450,7 @@ object CoreGraph {
|
||||
/** A case branch.
|
||||
*
|
||||
* All case patterns will initially be desugared to a
|
||||
* [[StructuralMatch]] and will be refined during further desugaring
|
||||
* [[StructuralPattern]] and will be refined during further desugaring
|
||||
* passes, some of which may depend on type checking.
|
||||
*
|
||||
* @param pattern the pattern to match the scrutinee against
|
||||
@ -459,7 +463,7 @@ object CoreGraph {
|
||||
* @param matchExpression the expression representing the possible
|
||||
* structure of the scrutinee
|
||||
*/
|
||||
case class StructuralMatch(matchExpression: Link[G])
|
||||
case class StructuralPattern(matchExpression: Link[G])
|
||||
|
||||
/** A pattern that matches on the scrutinee purely based on a type
|
||||
* subsumption judgement.
|
||||
@ -467,7 +471,7 @@ object CoreGraph {
|
||||
* @param matchExpression the expression representing the possible type
|
||||
* of the scrutinee
|
||||
*/
|
||||
case class TypeMatch(matchExpression: Link[G])
|
||||
case class TypePattern(matchExpression: Link[G])
|
||||
|
||||
/** A pattern that matches on the scrutinee based on a type subsumption
|
||||
* judgement and assigns a new name to it for use in the branch.
|
||||
@ -475,10 +479,10 @@ object CoreGraph {
|
||||
* @param matchExpression the expression representing the possible type
|
||||
* of the scrutinee, and its new name
|
||||
*/
|
||||
case class NamedMatch(matchExpression: Link[G])
|
||||
case class NamedPattern(matchExpression: Link[G])
|
||||
|
||||
/** A pattern that matches on any scrutinee. */
|
||||
case class FallbackMatch()
|
||||
case class FallbackPattern()
|
||||
|
||||
// === Comments =======================================================
|
||||
|
||||
@ -502,17 +506,61 @@ object CoreGraph {
|
||||
|
||||
/** A syntax error.
|
||||
*
|
||||
* @param errorNode the node representation of the syntax error
|
||||
* @param errorAst the raw AST representation of the syntax error
|
||||
*/
|
||||
case class SyntaxError(errorNode: Link[G])
|
||||
case class SyntaxError(errorAst: OpaqueData[AST, AstStorage])
|
||||
|
||||
// TODO [AA] Fill in the error types as they become evident
|
||||
/** Returned on an attempt to construct erroneous core.
|
||||
*
|
||||
* @param erroneousCore a [[MetaList]] containing the one-or-more core
|
||||
* nodes that were in an incorrect format
|
||||
*/
|
||||
case class ConstructionError(erroneousCore: Link[G])
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
// === Utility Functions ================================================
|
||||
// ======================================================================
|
||||
|
||||
/** Adds a link as a parent of the provided node.
|
||||
*
|
||||
* This should _only_ be used when the [[target]] field of [[link]]
|
||||
* points to [[node]].
|
||||
*
|
||||
* @param node the node to add a parent to
|
||||
* @param link the link to add as a parent
|
||||
* @param graph the graph in which this takes place
|
||||
* @param map the graph's parent storage
|
||||
*/
|
||||
def addParent(
|
||||
node: Node[CoreGraph],
|
||||
link: Link[CoreGraph]
|
||||
)(
|
||||
implicit graph: PrimGraph.GraphData[CoreGraph],
|
||||
map: ParentStorage
|
||||
): Unit = {
|
||||
import Node.ParentLinks._
|
||||
|
||||
node.parents = node.parents :+ link.ix
|
||||
}
|
||||
|
||||
/** Adds a node to the graph with its shape already set to a given shape.
|
||||
*
|
||||
* @param graph the graph to add the node to
|
||||
* @param ev evidence that the variant field is indexed
|
||||
* @tparam V the shape to set the node to
|
||||
* @return a refined node reference
|
||||
*/
|
||||
def addRefined[V <: Node.Shape](
|
||||
implicit graph: PrimGraph.GraphData[CoreGraph],
|
||||
ev: VariantIndexed[Node.Shape, V]
|
||||
): PrimGraph.Component.Refined[Node.Shape, V, Node[CoreGraph]] = {
|
||||
val node = graph.addNode()
|
||||
|
||||
setShape[V](node)
|
||||
PrimGraph.Component.Refined[Node.Shape, V, Node[CoreGraph]](node)
|
||||
}
|
||||
|
||||
/** Sets the shape of the provided [[node]] to [[Shape]].
|
||||
*
|
||||
* @param node the node to set
|
||||
@ -538,8 +586,9 @@ object CoreGraph {
|
||||
node: Node[CoreGraph]
|
||||
)(implicit graph: PrimGraph.GraphData[CoreGraph]): Boolean = {
|
||||
node match {
|
||||
case Shape.SyntaxError.any(_) => true
|
||||
case _ => false
|
||||
case Shape.SyntaxError.any(_) => true
|
||||
case Shape.ConstructionError.any(_) => true
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,9 @@
|
||||
package org.enso.compiler.test.core
|
||||
|
||||
import org.enso.compiler.test.CompilerTest
|
||||
import org.enso.core.CoreGraph.DefinitionGen.Node.LocationVal
|
||||
import org.enso.core.CoreGraph.DefinitionGen.{
|
||||
AstStorage,
|
||||
Link,
|
||||
LiteralStorage,
|
||||
NameStorage,
|
||||
@ -10,6 +12,7 @@ import org.enso.core.CoreGraph.DefinitionGen.{
|
||||
}
|
||||
import org.scalatest.BeforeAndAfterEach
|
||||
import org.enso.graph.{Graph => PrimGraph}
|
||||
import org.enso.syntax.text.AST
|
||||
|
||||
/** This file tests the primitive, low-level operations on core.
|
||||
*
|
||||
@ -22,7 +25,7 @@ import org.enso.graph.{Graph => PrimGraph}
|
||||
class CorePrimTest extends CompilerTest with BeforeAndAfterEach {
|
||||
|
||||
// === Test Setup ===========================================================
|
||||
import org.enso.core.CoreGraph.DefinitionGen.CoreGraph
|
||||
import org.enso.core.CoreGraph.DefinitionGen._
|
||||
import org.enso.core.CoreGraph.DefinitionGen.Link.Shape._
|
||||
import org.enso.core.CoreGraph.DefinitionGen.Node.Shape._
|
||||
import org.enso.core.CoreGraph.DefinitionGen.Node.Location._
|
||||
@ -33,12 +36,14 @@ class CorePrimTest extends CompilerTest with BeforeAndAfterEach {
|
||||
implicit var literalStorage: LiteralStorage = _
|
||||
implicit var parentStorage: ParentStorage = _
|
||||
implicit var nameStorage: NameStorage = _
|
||||
implicit var astStorage: AstStorage = _
|
||||
|
||||
override def beforeEach(): Unit = {
|
||||
graph = PrimGraph[CoreGraph]()
|
||||
literalStorage = LiteralStorage()
|
||||
parentStorage = ParentStorage()
|
||||
nameStorage = NameStorage()
|
||||
astStorage = AstStorage()
|
||||
}
|
||||
|
||||
// === Tests for Links ======================================================
|
||||
@ -124,6 +129,34 @@ class CorePrimTest extends CompilerTest with BeforeAndAfterEach {
|
||||
}
|
||||
}
|
||||
|
||||
node should "be able to be constructed without clobbering its fields" in {
|
||||
val emptyLink = graph.addLink()
|
||||
val nilLink = graph.addLink()
|
||||
val consNode = Node.addRefined[MetaList]
|
||||
|
||||
consNode.head = emptyLink
|
||||
consNode.tail = nilLink
|
||||
consNode.location = LocationVal[CoreGraph](20, 30)
|
||||
consNode.parents = Vector()
|
||||
|
||||
// Intentional re-assignment in reverse order to check for clobbering
|
||||
consNode.tail = nilLink
|
||||
consNode.head = emptyLink
|
||||
|
||||
consNode.head shouldEqual emptyLink
|
||||
consNode.tail shouldEqual nilLink
|
||||
consNode.sourceStart shouldEqual 20
|
||||
consNode.sourceEnd shouldEqual 30
|
||||
consNode.parents shouldEqual Vector()
|
||||
|
||||
consNode.wrapped match {
|
||||
case MetaList.any(_) => succeed
|
||||
case _ => fail
|
||||
}
|
||||
}
|
||||
|
||||
// === Tests for Node Shapes ================================================
|
||||
|
||||
nodeShape should "be able to be empty" in {
|
||||
val n1 = graph.addNode()
|
||||
|
||||
@ -807,13 +840,13 @@ class CorePrimTest extends CompilerTest with BeforeAndAfterEach {
|
||||
val n1 = graph.addNode()
|
||||
val l1 = graph.addLink()
|
||||
|
||||
Node.setShape[StructuralMatch](n1)
|
||||
Node.setShape[StructuralPattern](n1)
|
||||
|
||||
n1 match {
|
||||
case StructuralMatch.any(n1) =>
|
||||
case StructuralPattern.any(n1) =>
|
||||
n1.matchExpression = l1
|
||||
|
||||
n1.structuralMatch shouldEqual StructuralMatchVal(l1)
|
||||
n1.structuralPattern shouldEqual StructuralPatternVal(l1)
|
||||
case _ => fail
|
||||
}
|
||||
}
|
||||
@ -822,13 +855,13 @@ class CorePrimTest extends CompilerTest with BeforeAndAfterEach {
|
||||
val n1 = graph.addNode()
|
||||
val l1 = graph.addLink()
|
||||
|
||||
Node.setShape[TypeMatch](n1)
|
||||
Node.setShape[TypePattern](n1)
|
||||
|
||||
n1 match {
|
||||
case TypeMatch.any(n1) =>
|
||||
case TypePattern.any(n1) =>
|
||||
n1.matchExpression = l1
|
||||
|
||||
n1.typeMatch shouldEqual TypeMatchVal(l1)
|
||||
n1.typePattern shouldEqual TypePatternVal(l1)
|
||||
case _ => fail
|
||||
}
|
||||
}
|
||||
@ -837,13 +870,13 @@ class CorePrimTest extends CompilerTest with BeforeAndAfterEach {
|
||||
val n1 = graph.addNode()
|
||||
val l1 = graph.addLink()
|
||||
|
||||
Node.setShape[NamedMatch](n1)
|
||||
Node.setShape[NamedPattern](n1)
|
||||
|
||||
n1 match {
|
||||
case NamedMatch.any(n1) =>
|
||||
case NamedPattern.any(n1) =>
|
||||
n1.matchExpression = l1
|
||||
|
||||
n1.namedMatch shouldEqual NamedMatchVal(l1)
|
||||
n1.namedPattern shouldEqual NamedPatternVal(l1)
|
||||
case _ => fail
|
||||
}
|
||||
}
|
||||
@ -851,11 +884,11 @@ class CorePrimTest extends CompilerTest with BeforeAndAfterEach {
|
||||
nodeShape should "be able to represent fallback patterns" in {
|
||||
val n1 = graph.addNode()
|
||||
|
||||
Node.setShape[FallbackMatch](n1)
|
||||
Node.setShape[FallbackPattern](n1)
|
||||
|
||||
n1 match {
|
||||
case FallbackMatch.any(_) => succeed
|
||||
case _ => fail
|
||||
case FallbackPattern.any(_) => succeed
|
||||
case _ => fail
|
||||
}
|
||||
}
|
||||
|
||||
@ -894,17 +927,31 @@ class CorePrimTest extends CompilerTest with BeforeAndAfterEach {
|
||||
}
|
||||
|
||||
nodeShape should "be able to represent syntax errors" in {
|
||||
val n1 = graph.addNode()
|
||||
val l1 = graph.addLink()
|
||||
val n1 = graph.addNode()
|
||||
val ast = AST.Blank()
|
||||
|
||||
Node.setShape[SyntaxError](n1)
|
||||
|
||||
n1 match {
|
||||
case SyntaxError.any(n1) =>
|
||||
n1.errorNode = l1
|
||||
n1.errorAst = ast
|
||||
|
||||
n1.syntaxError shouldEqual SyntaxErrorVal(l1)
|
||||
n1.syntaxError shouldEqual SyntaxErrorVal(ast)
|
||||
case _ => fail
|
||||
}
|
||||
}
|
||||
|
||||
nodeShape should "be able to represent construction errors" in {
|
||||
val n1 = graph.addNode()
|
||||
val l1 = graph.addLink()
|
||||
|
||||
Node.setShape[ConstructionError](n1)
|
||||
|
||||
n1 match {
|
||||
case ConstructionError.any(n1) =>
|
||||
n1.erroneousCore = l1
|
||||
|
||||
n1.constructionError shouldEqual ConstructionErrorVal(l1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,4 @@ import org.enso.compiler.test.CompilerTest
|
||||
// - Linked List
|
||||
// - Parent Link walk to same place
|
||||
// - etc.
|
||||
class CoreTest extends CompilerTest {
|
||||
|
||||
}
|
||||
class CoreTest extends CompilerTest {}
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user