Skip to content

Commit c736e58

Browse files
committed
UnitAST -> RuntimeUnit, return Either
1 parent 4ed6c19 commit c736e58

File tree

1 file changed

+58
-54
lines changed

1 file changed

+58
-54
lines changed

runtime/src/main/scala/coulomb/runtime/runtime.scala

Lines changed: 58 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,31 @@ import coulomb.*
2222
import coulomb.syntax.*
2323
import coulomb.rational.Rational
2424

25-
sealed abstract class UnitAST:
26-
def *(rhs: UnitAST): UnitAST.Mul = UnitAST.Mul(this, rhs)
27-
def /(den: UnitAST): UnitAST.Div = UnitAST.Div(this, den)
28-
def ^(e: Rational): UnitAST.Pow = UnitAST.Pow(this, e)
29-
30-
object UnitAST:
31-
case class UnitType(path: String) extends UnitAST
32-
case class Mul(lhs: UnitAST, rhs: UnitAST) extends UnitAST
33-
case class Div(num: UnitAST, den: UnitAST) extends UnitAST
34-
case class Pow(b: UnitAST, e: Rational) extends UnitAST
35-
inline def of[U]: UnitAST = ${ meta.unitAST[U] }
25+
sealed abstract class RuntimeUnit:
26+
def *(rhs: RuntimeUnit): RuntimeUnit.Mul = RuntimeUnit.Mul(this, rhs)
27+
def /(den: RuntimeUnit): RuntimeUnit.Div = RuntimeUnit.Div(this, den)
28+
def ^(e: Rational): RuntimeUnit.Pow = RuntimeUnit.Pow(this, e)
29+
30+
object RuntimeUnit:
31+
case class UnitType(path: String) extends RuntimeUnit
32+
case class Mul(lhs: RuntimeUnit, rhs: RuntimeUnit) extends RuntimeUnit
33+
case class Div(num: RuntimeUnit, den: RuntimeUnit) extends RuntimeUnit
34+
case class Pow(b: RuntimeUnit, e: Rational) extends RuntimeUnit
35+
inline def of[U]: RuntimeUnit = ${ meta.unitRTU[U] }
3636

3737
package syntax {
38+
import scala.util.{Try, Success, Failure}
3839
import coulomb.conversion.*
3940

40-
extension [V](v: V)
41-
inline def withUnitRuntime[U](u: UnitAST)(using
41+
extension [V](vu: (V, RuntimeUnit))
42+
inline def toQuantity[U](using
4243
vi: ValueConversion[V, Rational],
4344
vo: ValueConversion[Rational, V]
44-
): Quantity[V, U] =
45-
vo(meta.kernelExpr[U](vi(v), u)).withUnit[U]
45+
): Either[String, Quantity[V, U]] =
46+
val (v, u) = vu
47+
Try(vo(meta.kernelExpr[U](vi(v), u)).withUnit[U]) match
48+
case Success(q) => Right(q)
49+
case Failure(e) => Left(e.getMessage)
4650
}
4751

4852
object meta:
@@ -52,36 +56,36 @@ object meta:
5256
import coulomb.conversion.coefficients.{meta => _, *}
5357
import coulomb.infra.meta.{*, given}
5458

55-
given ctx_UnitASTToExpr: ToExpr[UnitAST] with
56-
def apply(ast: UnitAST)(using Quotes): Expr[UnitAST] =
57-
ast match
58-
case UnitAST.UnitType(path) =>
59-
'{ UnitAST.UnitType(${ Expr(path) }) }
60-
case UnitAST.Mul(l, r) =>
61-
'{ UnitAST.Mul(${ Expr(l) }, ${ Expr(r) }) }
62-
case UnitAST.Div(n, d) =>
63-
'{ UnitAST.Div(${ Expr(n) }, ${ Expr(d) }) }
64-
case UnitAST.Pow(b, e) =>
65-
'{ UnitAST.Pow(${ Expr(b) }, ${ Expr(e) }) }
66-
67-
inline def kernelExpr[U](v: Rational, u: UnitAST): Rational =
59+
given ctx_RuntimeUnitToExpr: ToExpr[RuntimeUnit] with
60+
def apply(rtu: RuntimeUnit)(using Quotes): Expr[RuntimeUnit] =
61+
rtu match
62+
case RuntimeUnit.UnitType(path) =>
63+
'{ RuntimeUnit.UnitType(${ Expr(path) }) }
64+
case RuntimeUnit.Mul(l, r) =>
65+
'{ RuntimeUnit.Mul(${ Expr(l) }, ${ Expr(r) }) }
66+
case RuntimeUnit.Div(n, d) =>
67+
'{ RuntimeUnit.Div(${ Expr(n) }, ${ Expr(d) }) }
68+
case RuntimeUnit.Pow(b, e) =>
69+
'{ RuntimeUnit.Pow(${ Expr(b) }, ${ Expr(e) }) }
70+
71+
inline def kernelExpr[U](v: Rational, u: RuntimeUnit): Rational =
6872
${ kernelExprMeta[U]('v, 'u) }
6973

70-
def kernelExprMeta[U](v: Expr[Rational], u: Expr[UnitAST])(using
74+
def kernelExprMeta[U](v: Expr[Rational], u: Expr[RuntimeUnit])(using
7175
Quotes,
7276
Type[U]
7377
): Expr[Rational] =
7478
import quotes.reflect.*
7579
val cmp = stagingCompiler
76-
val astU = typeReprAST(TypeRepr.of[U])
77-
'{ kernelRuntime($v, $u, ${ Expr(astU) })(using $cmp) }
80+
val rtuU = typeReprRTU(TypeRepr.of[U])
81+
'{ kernelRuntime($v, $u, ${ Expr(rtuU) })(using $cmp) }
7882

79-
def kernelRuntime(v: Rational, astF: UnitAST, astT: UnitAST)(using
83+
def kernelRuntime(v: Rational, rtuF: RuntimeUnit, rtuT: RuntimeUnit)(using
8084
staging.Compiler
8185
): Rational =
8286
staging.run {
8387
import quotes.reflect.*
84-
(astTypeRepr(astF).asType, astTypeRepr(astT).asType) match
88+
(rtuTypeRepr(rtuF).asType, rtuTypeRepr(rtuT).asType) match
8589
case ('[uf], '[ut]) =>
8690
'{ ${ Expr(v) } * coefficientRational[uf, ut] }
8791
}
@@ -96,49 +100,49 @@ object meta:
96100
// I'm not even sorry.
97101
null.asInstanceOf[Expr[staging.Compiler]]
98102

99-
def unitAST[U](using Quotes, Type[U]): Expr[UnitAST] =
103+
def unitRTU[U](using Quotes, Type[U]): Expr[RuntimeUnit] =
100104
import quotes.reflect.*
101-
Expr(typeReprAST(TypeRepr.of[U]))
105+
Expr(typeReprRTU(TypeRepr.of[U]))
102106

103-
def astTypeRepr(using Quotes)(
104-
ast: UnitAST
107+
def rtuTypeRepr(using Quotes)(
108+
rtu: RuntimeUnit
105109
): quotes.reflect.TypeRepr =
106110
import quotes.reflect.*
107-
ast match
108-
case UnitAST.UnitType(path) => fqTypeRepr(path)
109-
case UnitAST.Mul(l, r) =>
110-
val ltr = astTypeRepr(l)
111-
val rtr = astTypeRepr(r)
111+
rtu match
112+
case RuntimeUnit.UnitType(path) => fqTypeRepr(path)
113+
case RuntimeUnit.Mul(l, r) =>
114+
val ltr = rtuTypeRepr(l)
115+
val rtr = rtuTypeRepr(r)
112116
TypeRepr.of[coulomb.`*`].appliedTo(List(ltr, rtr))
113-
case UnitAST.Div(n, d) =>
114-
val ntr = astTypeRepr(n)
115-
val dtr = astTypeRepr(d)
117+
case RuntimeUnit.Div(n, d) =>
118+
val ntr = rtuTypeRepr(n)
119+
val dtr = rtuTypeRepr(d)
116120
TypeRepr.of[coulomb.`/`].appliedTo(List(ntr, dtr))
117-
case UnitAST.Pow(b, e) =>
118-
val btr = astTypeRepr(b)
121+
case RuntimeUnit.Pow(b, e) =>
122+
val btr = rtuTypeRepr(b)
119123
val etr = rationalTE(e)
120124
TypeRepr.of[coulomb.`^`].appliedTo(List(btr, etr))
121125

122-
def typeReprAST(using Quotes)(
126+
def typeReprRTU(using Quotes)(
123127
tr: quotes.reflect.TypeRepr
124-
): UnitAST =
128+
): RuntimeUnit =
125129
import quotes.reflect.*
126130
tr match
127131
case AppliedType(op, List(lu, ru))
128132
if (op =:= TypeRepr.of[coulomb.`*`]) =>
129-
UnitAST.Mul(typeReprAST(lu), typeReprAST(ru))
133+
RuntimeUnit.Mul(typeReprRTU(lu), typeReprRTU(ru))
130134
case AppliedType(op, List(lu, ru))
131135
if (op =:= TypeRepr.of[coulomb.`/`]) =>
132-
UnitAST.Div(typeReprAST(lu), typeReprAST(ru))
136+
RuntimeUnit.Div(typeReprRTU(lu), typeReprRTU(ru))
133137
case AppliedType(op, List(b, e))
134138
if (op =:= TypeRepr.of[coulomb.`^`]) =>
135139
val rationalTE(ev) = e: @unchecked
136-
UnitAST.Pow(typeReprAST(b), ev)
140+
RuntimeUnit.Pow(typeReprRTU(b), ev)
137141
case t =>
138142
// should add checking for types with type-args here
139-
// possibly an explicit non dealiasting policy here would allow
143+
// possibly an explicit non dealirtuing policy here would allow
140144
// parameterized types to be handled via typedef aliases?
141-
UnitAST.UnitType(t.typeSymbol.fullName)
145+
RuntimeUnit.UnitType(t.typeSymbol.fullName)
142146

143147
def fqTypeRepr(using Quotes)(path: String): quotes.reflect.TypeRepr =
144148
fqTypeRepr(path.split('.').toIndexedSeq)

0 commit comments

Comments
 (0)