@@ -22,27 +22,31 @@ import coulomb.*
2222import coulomb .syntax .*
2323import 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
3737package 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
4852object 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