Skip to content

Commit

Permalink
More IR work and introducing the interpreter (#17)
Browse files Browse the repository at this point in the history
* Add Path.toList

* Exploration of pulling out Type into its own IR branch

* IR Work
Co-authored-by: Adam Fraser <[email protected]>

* Interpreter cleanup

Co-authored-by: Adam Fraser <[email protected]>

* More IR

* Splitting out Morphir IR into ValueModule to mirror morphir Elm's Morphir.IR.Value module

* Fix errors still some warnings

* IR changes

Co-authored-by: Adam Fraser <[email protected]>

* Exploration of pulling out Type into its own IR branch

* IR Work
Co-authored-by: Adam Fraser <[email protected]>

* Interpreter cleanup

Co-authored-by: Adam Fraser <[email protected]>

* More IR

* Splitting out Morphir IR into ValueModule to mirror morphir Elm's Morphir.IR.Value module

* Fix errors still some warnings

* IR changes

Co-authored-by: Adam Fraser <[email protected]>

* Small type changes

* Fixup and preparation for moving to using TypeModule and ValueModule

* More IR and Module cleanup

* Fix warnings and flag current broken functionality

* Fix warnings

* Formatting changes

Co-authored-by: Adam Fraser <[email protected]>
  • Loading branch information
DamianReeves and adamgfraser authored Feb 10, 2022
1 parent 067682b commit 1c4d56f
Show file tree
Hide file tree
Showing 18 changed files with 995 additions and 42 deletions.
3 changes: 3 additions & 0 deletions morphir-ir/shared/src/main/scala/zio/morphir/dsl.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package zio.morphir

object Dsl extends syntax.ValueSyntax
6 changes: 6 additions & 0 deletions morphir-ir/shared/src/main/scala/zio/morphir/ir/Literal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ sealed trait Literal[+A] {
def value: A
}
object Literal {
def boolean(value: Boolean): Bool = Bool(value)
def int(value: Int): WholeNumber = WholeNumber(java.math.BigInteger.valueOf(value.toLong))
def long(value: Long): WholeNumber = WholeNumber(java.math.BigInteger.valueOf(value))
def string(value: java.lang.String): String = Literal.String(value)
def wholeNumber(value: java.math.BigInteger): WholeNumber = WholeNumber(value)

final case class Bool(value: scala.Boolean) extends Literal[scala.Boolean]
final case class Char(value: scala.Char) extends Literal[scala.Char]
final case class String(value: java.lang.String) extends Literal[java.lang.String]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package zio.morphir.ir

object Module {
object ModuleModule {

type Definition[+Annotations] = MorphirIR.ModuleDefinition[Annotations]
val Definition = MorphirIR.ModuleDefinition
Expand All @@ -25,14 +25,14 @@ object Module {
}

trait ModuleSpecFor[A] {
import Module.*
import ModuleModule.*

def module: ModuleName
def spec: Specification[Any]
}

object ModuleSpecFor {
import Module.*
import ModuleModule.*

/** Summon the module specification for the given module/type. */
def apply[A](implicit specFor: ModuleSpecFor[A]): ModuleSpecFor[A] = specFor
Expand Down
88 changes: 86 additions & 2 deletions morphir-ir/shared/src/main/scala/zio/morphir/ir/MorphirIR.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package zio.morphir.ir

import zio.morphir.ir.{Literal => Lit}
import zio.morphir.ir.recursive.*
import zio.prelude._
import zio.prelude.fx._
Expand Down Expand Up @@ -68,8 +69,9 @@ sealed trait MorphirIR[+Annotations] { self =>
c.inValue.fold(f)
)
)
case c @ ValueCase.ListCase(_) => f(ValueCase.ListCase(c.elements.map(_.fold(f))))
case c @ ValueCase.LiteralCase(_) => f(c)
case c @ ValueCase.ListCase(_) => f(ValueCase.ListCase(c.elements.map(_.fold(f))))
case c @ ValueCase.LiteralCase(_) => f(c)
case c @ ValueCase.NativeApplyCase(_, _) => f(ValueCase.NativeApplyCase(c.function, c.arguments.map(_.fold(f))))
case c @ ValueCase.PatternMatchCase(_, _) =>
f(
ValueCase.PatternMatchCase(
Expand Down Expand Up @@ -193,6 +195,14 @@ sealed trait MorphirIR[+Annotations] { self =>

object MorphirIR {

def apply(
caseValue0: MorphirIRCase[MorphirIR[Any]]
): MorphirIR[Any] =
new MorphirIR[Any] {
def caseValue = caseValue0
def annotations = ZEnvironment.empty
}

def apply[Annotations](
caseValue0: MorphirIRCase[MorphirIR[Annotations]],
annotations0: ZEnvironment[Annotations]
Expand Down Expand Up @@ -229,6 +239,7 @@ object MorphirIR {

object Definition {
object WithTypeParams {

def unapply[Annotations](
ir: MorphirIR[Annotations]
): Option[(List[Name], DefinitionCase[TypeTree[Annotations]])] =
Expand Down Expand Up @@ -413,11 +424,84 @@ object MorphirIR {
}

object Value {
def apply(
caseValue0: ValueCase[Value[Any]]
): Value[Any] =
new Value[Any] {
override def caseValue: ValueCase[Value[Any]] = caseValue0
override def annotations: ZEnvironment[Any] = ZEnvironment.empty
}

def apply[Annotations](
caseValue0: ValueCase[Value[Annotations]],
annotations0: ZEnvironment[Annotations]
): Value[Annotations] =
new Value[Annotations] {
override def caseValue: ValueCase[Value[Annotations]] = caseValue0
override def annotations: ZEnvironment[Annotations] = annotations0
}

def field(name: Name)(record: Record[Any]): Field[Any] = Field(record, name, ZEnvironment.empty)
def patternMatch(scrutinee: Value[Any], cases: (Value[Any], Value[Any])*): PatternMatch[Any] =
PatternMatch(scrutinee, Chunk.fromIterable(cases), ZEnvironment.empty)
// def patternMatch[Annotations](
// scrutinee: Value[Annotations],
// annotations: ZEnvironment[Annotations],
// cases: (Value[Annotations], Value[Annotations])*
// ): PatternMatch[Annotations] =
// PatternMatch(scrutinee, Chunk.fromIterable(cases), annotations)

def record(fields: (Name, Value[Any])*): Record[Any] =
Record(Chunk.fromIterable(fields), ZEnvironment.empty)

def wholeNumber(value: java.math.BigInteger): Literal[Any, java.math.BigInteger] = {
println("In Value.wholeNumber")
Literal(Lit.wholeNumber(value), ZEnvironment.empty)
}

def string(value: String): Literal[Any, String] = {
println(s"In Value.string: $value")
val l = Literal(Lit.string(value), ZEnvironment.empty)
println(s"In Value.string: Literal: $l")
l
}

import ValueCase.*

final case class Field[+Annotations](
target: Value[Annotations],
name: Name,
annotations: ZEnvironment[Annotations]
) extends Value[Annotations] {
override lazy val caseValue: ValueCase[Value[Annotations]] = FieldCase(target, name)
}

final case class PatternMatch[+Annotations](
scrutinee: Value[Annotations],
cases: Chunk[(Value[Annotations], Value[Annotations])],
annotations: ZEnvironment[Annotations]
) extends Value[Annotations] {
override lazy val caseValue: ValueCase[Value[Annotations]] = PatternMatchCase(scrutinee, cases)
}

final case class Variable[+Annotations](name: Name, annotations: ZEnvironment[Annotations])
extends Value[Annotations] {
override lazy val caseValue: VariableCase = VariableCase(name)
}

final case class Record[+Annotations](
fields: Chunk[(Name, Value[Annotations])],
annotations: ZEnvironment[Annotations]
) extends Value[Annotations] {
override lazy val caseValue: ValueCase[Value[Annotations]] = RecordCase(fields)
}

final case class Literal[+Annotations, +V](
value: zio.morphir.ir.Literal[V],
annotations: ZEnvironment[Annotations]
) extends Value[Annotations] {
override lazy val caseValue: ValueCase[Value[Annotations]] = LiteralCase(value)
}
}

sealed trait Distribution[+Annotations] extends MorphirIR[Annotations] { self =>
Expand Down
3 changes: 2 additions & 1 deletion morphir-ir/shared/src/main/scala/zio/morphir/ir/Name.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ object Name {
/**
* Creates a new name from a chunk of strings without checking.
*/
private[ir] def unsafeMake(value: List[String]): Name = Name(value)
private[ir] def unsafeMake(value: List[String]): Name = Name(value)
private[ir] def unsafeMake(exactSegments: String*): Name = Name(exactSegments.toList)

def toList(name: Name): List[String] = name.toList

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package zio.morphir.ir

sealed trait NativeFunction {}
object NativeFunction {
case object Addition extends NativeFunction
}
1 change: 0 additions & 1 deletion morphir-ir/shared/src/main/scala/zio/morphir/ir/Type.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package zio.morphir.ir
import zio.{Chunk, ZEnvironment}

object Type {
type Type[+Annotations] = MorphirIR.Type[Annotations]
val Type = MorphirIR.Type
Expand Down
183 changes: 183 additions & 0 deletions morphir-ir/shared/src/main/scala/zio/morphir/ir/TypeModule.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package zio.morphir.ir

import zio.{Chunk, ZEnvironment}
import zio.prelude.*

object TypeModule {

sealed trait Type[+Annotations] { self =>
// import TypeCase.*

final def asType: Type[Annotations] = self

def annotations: ZEnvironment[Annotations]
def caseValue: TypeCase[Type[Annotations]]

def fold[Z](f: TypeCase[Z] => Z): Z = self.caseValue match {
case c @ TypeCase.ExtensibleRecordCase(_, _) => f(TypeCase.ExtensibleRecordCase(c.name, c.fields.map(_.fold(f))))
case c @ TypeCase.FieldCase(_, _) => f(TypeCase.FieldCase(c.name, c.fieldType.fold(f)))
case c @ TypeCase.FunctionCase(_, _) =>
f(TypeCase.FunctionCase(c.paramTypes.map(_.fold(f)), c.returnType.fold(f)))
case c @ TypeCase.RecordCase(_) => f(TypeCase.RecordCase(c.fields.map(_.fold(f))))
case c @ TypeCase.ReferenceCase(_, _) => f(TypeCase.ReferenceCase(c.typeName, c.typeParams.map(_.fold(f))))
case c @ TypeCase.TupleCase(_) => f(TypeCase.TupleCase(c.elementTypes.map(_.fold(f))))
case _ @TypeCase.UnitCase => f(TypeCase.UnitCase)
case c @ TypeCase.VariableCase(_) => f(c)
}

def transformDown[Annotations0 >: Annotations](
f: Type[Annotations0] => Type[Annotations0]
): Type[Annotations0] = {
def loop(recursive: Type[Annotations0]): Type[Annotations] =
Type(f(recursive).caseValue.map(loop), annotations)
loop(self)
}
}

object Type {
import TypeCase.*

def apply[Annotations](
caseValue0: TypeCase[Type[Annotations]],
annotations0: ZEnvironment[Annotations]
): Type[Annotations] =
new Type[Annotations] {
override def caseValue: TypeCase[Type[Annotations]] = caseValue0
override def annotations: ZEnvironment[Annotations] = annotations0
}

def ref(name: FQName): Reference[Any] = Reference(name, Chunk.empty, ZEnvironment.empty)

/**
* Creates a type variable with the given `name`.
*/
def variable(name: Name): Variable[Any] = Variable(name, ZEnvironment.empty)
def variable(name: String): Variable[Any] = variable(Name(name))
val unit: Type[Any] = Unit(ZEnvironment.empty)

final case class Unit[+Annotations](annotations: ZEnvironment[Annotations]) extends Type[Annotations] {
override val caseValue: TypeCase[Type[Annotations]] = UnitCase
}

final case class Field[+Annotations](
name: Name,
fieldType: Type[Annotations],
annotations: ZEnvironment[Annotations]
) extends Type[Annotations] {
override lazy val caseValue: FieldCase[Type[Annotations]] = FieldCase(name, fieldType)
}
object Field {

object Case {
def unapply[Annotations](field: Field[Annotations]): Option[FieldCase[Type[Annotations]]] =
Some(field.caseValue)
}
}

final case class Reference[+Annotations](
name: FQName,
typeParams: Chunk[Type[Annotations]],
annotations: ZEnvironment[Annotations]
) extends Type[Annotations] {
override lazy val caseValue: ReferenceCase[Type[Annotations]] = ReferenceCase(name, typeParams)
}

object Reference {
object Case {
def unapply[Annotations](reference: Reference[Annotations]): Option[ReferenceCase[Type[Annotations]]] =
Some(reference.caseValue)
}
}

final case class Variable[+Annotations](name: Name, annotations: ZEnvironment[Annotations])
extends Type[Annotations] {
override lazy val caseValue: VariableCase = VariableCase(name)
}
object Variable {
object Case {
def unapply[Annotations](variable: Variable[Annotations]): Option[VariableCase] =
Some(variable.caseValue)
}
}
}

sealed trait TypeCase[+Self] { self =>
import TypeCase.*
def map[B](f: Self => B): TypeCase[B] = self match {
case c @ ExtensibleRecordCase(_, _) => ExtensibleRecordCase(c.name, c.fields.map(f))
case c @ FieldCase(_, _) => FieldCase(c.name, f(c.fieldType))
case c @ FunctionCase(_, _) => FunctionCase(c.paramTypes.map(f), f(c.returnType))
case c @ ReferenceCase(_, _) => ReferenceCase(c.typeName, c.typeParams.map(f))
case c @ TupleCase(_) => TupleCase(c.elementTypes.map(f))
case UnitCase => UnitCase
case c @ VariableCase(_) => VariableCase(c.name)
case c @ RecordCase(_) => RecordCase(c.fields.map(f))
}
}

object TypeCase {
final case class ExtensibleRecordCase[+Self](name: Name, fields: Chunk[Self]) extends TypeCase[Self]
final case class FunctionCase[+Self](paramTypes: List[Self], returnType: Self) extends TypeCase[Self]
final case class RecordCase[+Self](fields: Chunk[Self]) extends TypeCase[Self]
final case class ReferenceCase[+Self](typeName: FQName, typeParams: Chunk[Self]) extends TypeCase[Self]
final case class TupleCase[+Self](elementTypes: List[Self]) extends TypeCase[Self]
case object UnitCase extends TypeCase[Nothing]
final case class VariableCase(name: Name) extends TypeCase[Nothing]
final case class FieldCase[+Self](name: Name, fieldType: Self) extends TypeCase[Self]

implicit val TypeCaseForEach: ForEach[TypeCase] =
new ForEach[TypeCase] {
def forEach[G[+_]: IdentityBoth: Covariant, A, B](fa: TypeCase[A])(f: A => G[B]): G[TypeCase[B]] =
fa match {
case ExtensibleRecordCase(name, fields) =>
fields.forEach(f).map(fields => ExtensibleRecordCase(name, fields))
case FunctionCase(paramTypes, returnType) =>
paramTypes
.forEach(f)
.zipWith(f(returnType))((paramTypes, returnType) => FunctionCase(paramTypes, returnType))
case RecordCase(fields) =>
fields.forEach(f).map(fields => RecordCase(fields))
case ReferenceCase(typeName, typeParams) =>
typeParams.forEach(f).map(typeParams => ReferenceCase(typeName, typeParams))
case TupleCase(elementTypes) =>
elementTypes.forEach(f).map(elementTypes => TupleCase(elementTypes))
case UnitCase =>
UnitCase.succeed
case VariableCase(name) =>
VariableCase(name).succeed
case FieldCase(name, fieldType) =>
f(fieldType).map(fieldType => FieldCase(name, fieldType))
}
}
}

final case class TypeArg[+Annotations](
name: Name,
tpe: Type[Annotations]
)

final case class Constructors[+Annotations](items: Map[Name, TypeArg[Annotations]])

sealed trait Specification[+Annotations] {
def annotations: ZEnvironment[Annotations]
}

object Specification {
final case class TypeAliasSpecification[+Annotations](
typeParams: Chunk[Name],
expr: Type[Annotations],
annotations: ZEnvironment[Annotations]
) extends Specification[Annotations]

final case class OpaqueTypeSpecification[+Annotations](
typeParams: Chunk[Name],
annotations: ZEnvironment[Annotations]
) extends Specification[Annotations]

final case class CustomTypeSpecification[+Annotations](
typeParams: Chunk[Name],
expr: Type[Annotations],
annotations: ZEnvironment[Annotations]
) extends Specification[Annotations]
}
}
Loading

0 comments on commit 1c4d56f

Please sign in to comment.