8000 Comparable by edwardpeters · Pull Request #506 · finos/morphir-scala · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Comparable #506

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

Merged
merged 8 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"src/Morphir/Examples/App/PatternMatchTests.elm": "2f8139955168de0e9e7061aa351e466c",
"src/Morphir/Examples/App/RecordTests.elm": "818e85f5a21e5808bb487010d75d57cd",
"src/Morphir/Examples/App/ResultTests.elm": "fcc4d906b84e0f249847a016c8bcf70b",
"src/Morphir/Examples/App/SdkBasicTests.elm": "d93505a0ced9d9a2cc1d37d2f1e07040",
"src/Morphir/Examples/App/SdkBasicTests.elm": "6b57ef7274389db9803e9a523f33420f",
"src/Morphir/Examples/App/SetTests.elm": "477fc1e73a0eab237ee69ca52275ee1e",
"src/Morphir/Examples/App/SimpleTests.elm": "443d3bfdd8a53223afbcbe215b815099",
"src/Morphir/Examples/App/StringTests.elm": "0cfee84db5c29c83b0fce262b351e09d",
Expand Down

Large diffs are not rendered by default.

10000
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,62 @@ sdkMinTestList ctx =



-----
{-| Test: SdkBasics/orderToString
-}
sdkOrderToStringTest : Order -> String
sdkOrderToStringTest a =
case a of
LT ->
"LT"

EQ ->
"EQ"

GT ->
"GT"


sdkLessThanTest : comparable -> comparable -> Bool
sdkLessThanTest a b =
a < b

{-| Test: SdkBasics/greaterThan
-}
sdkGreaterThanTest : comparable -> comparable -> Bool
sdkGreaterThanTest a b =
a > b

{-| Test: SdkBasics/lessThanOrEqual
-}
sdkLessThanOrEqualTest : comparable -> comparable -> Bool
sdkLessThanOrEqualTest a b =
a <= b

{-| Test: SdkBasics/greaterThanOrEqual
-}
sdkGreaterThanOrEqualTest : comparable -> comparable -> Bool
sdkGreaterThanOrEqualTest a b =
a >= b

{-| Test: SdkBasics/max
-}
sdkMaxTest : comparable -> comparable -> comparable
sdkMaxTest a b =
max a b

{-| Test: SdkBasics/min
-}
sdkMinTest : comparable -> comparable -> comparable
sdkMinTest a b =
min a b

{-| Test: SdkBasics/compare
-}
sdkCompareTest : comparable -> comparable -> Order
sdkCompareTest a b =
compare a b

-----


Expand Down
21 changes: 13 additions & 8 deletions morphir/runtime/src/org/finos/morphir/runtime/Extractors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,31 @@ object Extractors {
object FQString {
def unapply(fqName: FQName): Option[String] = Some(fqName.toString())
}
object FQStringTitleCase {
def unapply(fqName: FQName): Option[String] = Some(fqName.toStringTitleCase)
}
object Types {
object ListRef {
def unapply(tpe: UType): Option[UType] =
tpe match {
// TODO: The SDK specification should make these names available, without requiring a type argument
case Type.Reference(_, FQString("Morphir.SDK:List:list"), List(elementType)) =>
case Type.Reference(_, FQStringTitleCase("Morphir.SDK:List:List"), List(elementType)) =>
Some(elementType)
case _ => None
}
}

object SetRef {
def unapply(tpe: UType): Option[UType] =
tpe match {
case Type.Reference(_, FQString("Morphir.SDK:Set:set"), List(elementType)) =>
case Type.Reference(_, FQStringTitleCase("Morphir.SDK:Set:Set"), List(elementType)) =>
Some(elementType)
case _ => None
}
}
object MaybeRef {
def unapply(tpe: UType): Option[UType] =
tpe match {
case Type.Reference(_, FQString("Morphir.SDK:Maybe:maybe"), List(elementType)) =>
case Type.Reference(_, FQStringTitleCase("Morphir.SDK:Maybe:Maybe"), List(elementType)) =>
Some(elementType)
case _ => None
}
Expand All @@ -46,15 +48,15 @@ object Extractors {
object ResultRef {
def unapply(tpe: UType): Option[(UType, UType)] =
tpe match {
case Type.Reference(_, FQString("Morphir.SDK:Result:result"), List(keyType, valType)) =>
case Type.Reference(_, FQStringTitleCase("Morphir.SDK:Result:Result"), List(keyType, valType)) =>
Some((keyType, valType))
case _ => None
}
}
object DictRef {
def unapply(tpe: UType): Option[(UType, UType)] =
tpe match {
case Type.Reference(_, FQString("Morphir.SDK:Dict:dict"), List(keyType, valType)) =>
case Type.Reference(_, FQStringTitleCase("Morphir.SDK:Dict:Dict"), List(keyType, valType)) =>
Some((keyType, valType))
case _ => None
}
Expand All @@ -69,6 +71,9 @@ object Extractors {
case _ => false
}
}
object OrderRef extends CommonReference {
final val tpe = Basics.orderType
}

object IntRef extends CommonReference {
final val tpe = Basics.intType
Expand Down Expand Up @@ -182,15 +187,15 @@ object Extractors {
object JustConstructor {
def unapply(value: TypedValue): Option[TypedValue] =
value match {
case Value.Apply(_, Value.Constructor(_, FQString("Morphir.SDK:Maybe:just")), something) =>
case Value.Apply(_, Value.Constructor(_, FQStringTitleCase("Morphir.SDK:Maybe:Just")), something) =>
Some(something)
case _ => None
}
}
object NothingConstructor {
def unapply(value: TypedValue): Boolean =
value match {
case Value.Constructor(_, FQString("Morphir.SDK:Maybe:nothing")) =>
case Value.Constructor(_, FQStringTitleCase("Morphir.SDK:Maybe:Nothing")) =>
true
case _ => false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ object EvaluatorQuick {
case DecimalRef() => Concept.Decimal
case LocalDateRef() => Concept.LocalDate
case LocalTimeRef() => Concept.LocalTime
case OrderRef() => Concept.Order
case MonthRef() => Concept.Month
case DayOfWeekRef() => Concept.DayOfWeek

Expand Down Expand Up @@ -155,7 +156,12 @@ object EvaluatorQuick {
Data.Int32(value.toInt)
case (Concept.Int64, RTValue.Primitive.Int(value)) =>
Data.Int64(value.toLong)

case (Concept.Order, RTValue.ConstructorResult(FQStringTitleCase("Morphir.SDK:Basics:GT"), List())) =>
Data.Order(1)
case (Concept.Order, RTValue.ConstructorResult(FQStringTitleCase("Morphir.SDK:Basics:LT"), List())) =>
Data.Order(-1)
case (Concept.Order, RTValue.ConstructorResult(FQStringTitleCase("Morphir.SDK:Basics:EQ"), List())) =>
Data.Order(0)
case (Concept.String, RTValue.Primitive.String(value)) =>
Data.String(value)
case (Concept.Boolean, RTValue.Primitive.Boolean(value)) =>
Expand Down Expand Up @@ -187,22 +193,25 @@ object EvaluatorQuick {
case (Concept.Set(elementConcept), RTValue.Set(elements)) =>
val inners = elements.map(element => resultAndConceptToData(element, elementConcept))
Data.Set(inners, elementConcept)
case (Concept.Optional(elementShape), RTValue.ConstructorResult(FQString("Morphir.SDK:Maybe:nothing"), List())) =>
case (
Concept.Optional(elementShape),
RTValue.ConstructorResult(FQStringTitleCase("Morphir.SDK:Maybe:Nothing"), List())
) =>
Data.Optional.None(elementShape)
case (
shape @ Concept.Result(_, okType),
RTValue.ConstructorResult(FQString("Morphir.SDK:Result:ok"), List(value))
RTValue.ConstructorResult(FQStringTitleCase("Morphir.SDK:Result:Ok"), List(value))
) =>
Data.Result.Ok(resultAndConceptToData(value, okType), shape)
case (
shape @ Concept.Result(errType, _),
RTValue.ConstructorResult(FQString("Morphir.SDK:Result:err"), List(value))
RTValue.ConstructorResult(FQStringTitleCase("Morphir.SDK:Result:Err"), List(value))
) =>
Data.Result.Err(resultAndConceptToData(value, errType), shape)
case (
Concept.Optional(elementShape),
RTValue.ConstructorResult(
FQString("Morphir.SDK:Maybe:just"),
FQStringTitleCase("Morphir.SDK:Maybe:Just"),
List(value)
)
) => Data.Optional.Some(resultAndConceptToData(value, elementShape))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ object DictSDK {
val newValue = evaluator.handleApplyResult(Type.UType.Unit(()), alterRaw, currValue)

newValue match {
case RTValue.ConstructorResult(FQString("Morphir.SDK:Maybe:just"), List(value)) =>
case RTValue.ConstructorResult(FQStringTitleCase("Morphir.SDK:Maybe:Just"), List(value)) =>
dict += ((targetKeyRaw, value))
case RTValue.ConstructorResult(FQString("Morphir.SDK:Maybe:nothing"), _) =>
case RTValue.ConstructorResult(FQStringTitleCase("Morphir.SDK:Maybe:Nothing"), _) =>
dict.remove(targetKeyRaw)
case _ =>
throw new UnexpectedType(
Expand Down Expand Up @@ -434,6 +434,9 @@ object Native {
val nothing: SDKConstructor = SDKConstructor(List())
val ok: SDKConstructor = SDKConstructor(List(Type.variable("contents")))
val err: SDKConstructor = SDKConstructor(List(Type.variable("contents")))
val gt: SDKConstructor = SDKConstructor(List())
val lt: SDKConstructor = SDKConstructor(List())
val eq: SDKConstructor = SDKConstructor(List())

val nativeCtors: Map[FQName, SDKConstructor] = Map(
FQName.fromString("Morphir.SDK:Maybe:just") -> just,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1947,6 +1947,63 @@ object EvaluatorMDMTests extends MorphirBaseSpec {
)
)
),
suite("SDK Comparable Tests")(
testEvalMultiple("LessThan")("sdkBasicsTests", "sdkLessThanTest", List((1, 2), (1, 3)))(Data.Boolean(true)),
testEvalMultiple("GreaterThan")("sdkBasicsTests", "sdkGreaterThanTest", List(1, 1))(Data.Boolean(false)),
testEvalMultiple("LessThanOrEqual")("sdkBasicsTests", "sdkLessThanOrEqualTest", List("Blue", "Blue"))(
Data.Boolean(true)
),
testEvalMultiple("GreaterThanOrEqual")(
"sdkBasicsTests",
"sdkGreaterThanOrEqualTest",
List(List(1, 2), List(1, 2, 3))
)(Data.Boolean(false)),
testEvalMultiple("Max")("sdkBasicsTests", "sdkMaxTest", List(1, 2))(Data.Int(2)),
testEvalMultiple("Min")("sdkBasicsTests", "sdkMinTest", List("Blue", "Red"))(Data.String("Blue")),
testEvalMultiple("Min if Equal")("sdkBasicsTests", "sdkMinTest", List("Blue", "Blue"))(Data.String("Blue")),
testEvalMultiple("Compare Int")("sdkBasicsTests", "sdkCompareTest", List(1, 2))(Data.Order(-1)),
testEvalMultiple("Compare Float")("sdkBasicsTests", "sdkCompareTest", List(2.0, 1.0))(Data.Order(1)),
testEvalMultiple("Compare String")("sdkBasicsTests", "sdkCompareTest", List("Red", "Red"))(Data.Order(0)),
testEvalMultiple("Compare Char")("sdkBasicsTests", "sdkCompareTest", List('r', 'b'))(Data.Order(1)),
testEvalMultiple("Compare List")("sdkBasicsTests", "sdkCompareTest", List(List(1, 0), List(1, 2)))(
Data.Order(-1)
),
testEvalMultiple("Compare List Different Length")(
"sdkBasicsTests",
"sdkCompareTest",
List(List(1, 0), List(1, 0, 0))
)(Data.Order(-1)),
testEvalMultiple("Compare List Different Length and Values")(
"sdkBasicsTests",
"sdkCompareTest",
List(List(1, 1), List(1, 0, 0))
)(Data.Order(1)),
testEvalMultiple("Compare List of Tuples")(
"sdkBasicsTests",
"sdkCompareTest",
List(
List((1, "Blue"), (1, "Green")),
List((1, "Blue"), (1, "An utter lack of any color, even black or white"))
)
)(Data.Order(1)),
testEvalMultiple("Compare Tuple of Lists")(
"sdkBasicsTests",
"sdkCompareTest",
List((List(1, 2), List("Red, Blue")), (List(1, 2), List("Red, Green")))
)(Data.Order(-1)),
testEvalMultiple("Compare Tuple")("sdkBasicsTests", "sdkCompareTest", List((0, 1, 2), (0, 2, 1)))(
Data.Order(-1)
),
testEval("Input LT")("sdkBasicsTests", "sdkOrderToStringTest", Data.Order(-1))(
Data.String("LT")
),
testEval("Input GT")("sdkBasicsTests", "sdkOrderToStringTest", Data.Order(1))(
Data.String("GT")
),
testEval("Input EQ")("sdkBasicsTests", "sdkOrderToStringTest", Data.Order(0))(
Data.String("EQ")
)
),
suite("SDK Basics Tests")(
testEval("Ceiling")("sdkBasicsTests", "basicsCeilingTest", 3.88)(Data.Int(4)),
testEval("Floor")("sdkBasicsTests", "basicsFloorTest", 3.88)(Data.Int(3)),
Expand Down
3 changes: 3 additions & 0 deletions morphir/src/org/finos/morphir/datamodel/Concept.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ object Concept {
val LocalTime = Concept.LocalTime
type Char = Concept.Char.type
val Char = Concept.Char
type Order = Concept.Order.type
val Order = Concept.Order
type Unit = Concept.Unit.type
val Unit = Concept.Unit
}
Expand All @@ -100,6 +102,7 @@ object Concept {
case object DayOfWeek extends Basic[java.time.DayOfWeek]
case object LocalTime extends Basic[java.time.LocalTime]
case object Char extends Basic[scala.Char]
case object Order extends Basic[Int]
case object Unit extends Basic[scala.Unit]
case object Nothing extends Basic[scala.Nothing]

Expand Down
6 changes: 4 additions & 2 deletions morphir/src/org/finos/morphir/datamodel/Data.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ object Data {
case class LocalTime(value: java.time.LocalTime) extends Basic[java.time.LocalTime] {
val shape: Concept = Concept.LocalTime
}
case class Char(value: scala.Char) extends Basic[scala.Char] { val shape: Concept = Concept.Char }
case object Unit extends Basic[scala.Unit] { val shape: Concept = Concept.Unit }
case class Char(value: scala.Char) extends Basic[scala.Char] { val shape: Concept = Concept.Char }
case class Order(value: Int) extends Basic[Int] { val shape: Concept = Concept.Order }
case object Unit extends Basic[scala.Unit] { val shape: Concept = Concept.Unit }

// Needed for Scala 3 extension methods to work
object Boolean {}
Expand All @@ -82,6 +83,7 @@ object Data {
object DayOfWeek {}
object LocalTime {}
object Char {}
object Order {}

/**
* See notes on Concept.Enum for information on how this type is modelled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ object ToMorphirType {
case Concept.DayOfWeek => dayOfWeekUType.as
case Concept.LocalTime => localTimeUType.as
case Concept.Char => charUType.as
case Concept.Order => toUTypeConverter(sdk.Basics.orderType)
case Concept.Unit => unitUType.as
case Concept.Alias(name, _) => toUTypeConverter(T.reference(name))
case Concept.Enum(name, _) => toUTypeConverter(T.reference(name))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ trait ToMorphirTypedValueInstancesLowPriority { self: ToMorphirValueFunctions =>
V.reference(FQName.fromString("Morphir.SDK:LocalTime:fromMilliseconds")),
V.intTyped(value.get(ChronoField.MILLI_OF_DAY))
)

case Data.Order(intVal) =>
if (intVal == 0) V.constructor("Morphir.SDK:Basics:EQ", sdk.Basics.orderType)
else if (intVal > 0) V.constructor("Morphir.SDK:Basics:GT", sdk.Basics.orderType)
else V.constructor("Morphir.SDK:Basics:LT", sdk.Basics.orderType)

case Data.Month(value) => value match {
case Month.JANUARY => V.constructor("Morphir.SDK:LocalDate:January", value.morphirType)
case Month.FEBRUARY => V.constructor("Morphir.SDK:LocalDate:February", value.morphirType)
Expand Down
4 changes: 4 additions & 0 deletions morphir/src/org/finos/morphir/runtime/Coercer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ object Coercer {
def coerce(result: RTValue): RTValue.Primitive.Numeric[T] =
RTValue.coerceNumeric(result).asInstanceOf[RTValue.Primitive.Numeric[T]]
}
implicit val comparableCoercer: Coercer[RTValue.Comparable] =
new Coercer[RTValue.Comparable] {
def coerce(result: RTValue): RTValue.Comparable = RTValue.coerceComparable(result)
}

implicit val fallbackNumericCoercer: Coercer[RTValue.Primitive.Numeric[_]] =
new Coercer[RTValue.Primitive.Numeric[_]] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ object MorphirRuntimeError {
}
final case class FailedCoercion(message: String) extends EvaluationError

final case class IllegalValue(message: String) extends EvaluationError
final case class IllegalValue(cause: String, context: String = "") extends EvaluationError {
def message = s"$cause . $context"
def withContext(newContex 79D7 t: String) = this.copy(context = context + "\n" + newContext)
}

final case class WrongNumberOfArguments(function: RTValue.NativeFunctionResult, applied: Int)
extends EvaluationError {
Expand Down Expand Up @@ -90,7 +93,7 @@ object MorphirRuntimeError {
}
object LookupError {
case class MissingPackage(pkgName: PackageName, context: String = "") extends LookupError {
def message = s"Package ${pkgName.toString} not found"
def message = s"Package ${pkgName.toString} not found. $context"
def withContext(newContext: String) = this.copy(context = context + "\n" + newContext)
}
case class MissingModule(pkgName: PackageName, modName: ModuleName, context: String = "")
Expand Down
Loading
0