@@ -2,6 +2,11 @@ module L4.Evaluate.ValueLazy where
22
33import Base
44import Control.Concurrent (ThreadId )
5+ import Data.Aeson (ToJSON (.. ), object , (.=) )
6+ import qualified Data.Aeson as Aeson
7+ import qualified Data.Aeson.Key as Key
8+ import Data.Ratio (numerator , denominator )
9+ import qualified Data.Vector as Vector
510import Data.Time (Day , UTCTime )
611import Data.Time.LocalTime (TimeOfDay )
712import L4.Syntax
@@ -242,3 +247,72 @@ instance NFData TernaryBuiltinFun where
242247 rnf TernaryAlwaysBetween = ()
243248 rnf TernaryTimeFromHMS = ()
244249 rnf TernaryDatetimeFromDTZ = ()
250+
251+ -- ----------------------------------------------------------------------------
252+ -- ToJSON instances for batch --json output
253+ -- ----------------------------------------------------------------------------
254+
255+ -- | Get the constructor name as Text from a Resolved name.
256+ resolvedNameText :: Resolved -> Text
257+ resolvedNameText = rawNameToText . rawName . getOriginal
258+
259+ -- | Flatten a ValCons/ValNil chain into a JSON array.
260+ -- If the structure is not a proper list, fall back to a two-element array.
261+ flattenList :: ToJSON a => a -> a -> Aeson. Value
262+ flattenList x xs = case toJSON xs of
263+ Aeson. Array arr -> Aeson. Array (Vector. cons (toJSON x) arr)
264+ _ -> toJSON [toJSON x, toJSON xs]
265+
266+ instance ToJSON NF where
267+ toJSON (MkNF val) = toJSON val
268+ toJSON Omitted = Aeson. Null
269+
270+ instance ToJSON a => ToJSON (Value a ) where
271+ toJSON (ValNumber r)
272+ | denominator r == 1 = toJSON (numerator r)
273+ | otherwise = toJSON (fromRational r :: Double )
274+ toJSON (ValString s) = toJSON s
275+ toJSON (ValDate d) = toJSON (show d)
276+ toJSON (ValTime t) = toJSON (show t)
277+ toJSON (ValDateTime utc tz) = object [" utc" .= utc, " timezone" .= tz]
278+ toJSON ValNil = toJSON ([] :: [Aeson. Value ])
279+ toJSON (ValCons x xs) = flattenList x xs
280+ toJSON (ValConstructor name [] )
281+ | cname == " NOTHING" = Aeson. Null
282+ | cname == " EMPTY" = toJSON ([] :: [Aeson. Value ])
283+ | cname == " TRUE" = Aeson. Bool True
284+ | cname == " FALSE" = Aeson. Bool False
285+ | otherwise = toJSON cname
286+ where cname = resolvedNameText name
287+ toJSON (ValConstructor name [v])
288+ | resolvedNameText name == " JUST" = toJSON v
289+ toJSON (ValConstructor name fields) = object
290+ [ Key. fromText (resolvedNameText name) .= toJSON fields ]
291+ toJSON (ValClosure {}) = toJSON (" <function>" :: Text )
292+ toJSON (ValObligation {}) = toJSON (" <obligation>" :: Text )
293+ toJSON (ValROp {}) = toJSON (" <deferred-op>" :: Text )
294+ toJSON (ValNullaryBuiltinFun {}) = toJSON (" <builtin>" :: Text )
295+ toJSON (ValUnaryBuiltinFun {}) = toJSON (" <builtin>" :: Text )
296+ toJSON (ValBinaryBuiltinFun {}) = toJSON (" <builtin>" :: Text )
297+ toJSON (ValTernaryBuiltinFun {}) = toJSON (" <builtin>" :: Text )
298+ toJSON (ValPartialTernary {}) = toJSON (" <partial>" :: Text )
299+ toJSON (ValPartialTernary2 {}) = toJSON (" <partial>" :: Text )
300+ toJSON (ValUnappliedConstructor r) = toJSON (resolvedNameText r)
301+ toJSON (ValAssumed r) = toJSON (" <assumed:" <> resolvedNameText r <> " >" :: Text )
302+ toJSON (ValEnvironment {}) = toJSON (" <environment>" :: Text )
303+ toJSON (ValBreached reason) = object [" breached" .= toJSON reason]
304+
305+ instance ToJSON a => ToJSON (ReasonForBreach a ) where
306+ toJSON (DeadlineMissed deadline now elapsed _party action limit) = object
307+ [ " type" .= (" deadline_missed" :: Text )
308+ , " deadline" .= deadline
309+ , " now" .= now
310+ , " elapsed" .= (fromRational elapsed :: Double )
311+ , " action" .= show action
312+ , " limit" .= (fromRational limit :: Double )
313+ ]
314+ toJSON (ExplicitBreach mParty mReason) = object
315+ [ " type" .= (" explicit_breach" :: Text )
316+ , " party" .= mParty
317+ , " reason" .= mReason
318+ ]
0 commit comments