packages feed

souffle-haskell 3.3.0 → 3.4.0

raw patch · 11 files changed

+364/−187 lines, 11 filesdep −containersdep −neat-interpolationdep −template-haskell

Dependencies removed: containers, neat-interpolation, template-haskell

Files

CHANGELOG.md view
@@ -3,6 +3,20 @@ All notable changes to this project (as seen by library users) will be documented in this file. The CHANGELOG is available on [Github](https://github.com/luc-tielen/souffle-haskell.git/CHANGELOG.md). +## [3.4.0] - 2022-05-15++### Changed++- Loosen the constraint that only types that are simple products that only+  contain directly marshallable types like `Int32`, `Word32`, ... Now also+  newtypes are allowed to be serialized, as well as product types inside other+  product types (as long as all the fields implement the 'Marshal' typeclass).++### Fixed++- Check if a type is a simple product type consisting of only types supported by+  Datalog. (This had a small bug for facts with more than 4 arguments.)+ ## [3.3.0] - 2022-02-27  ### Added
lib/Language/Souffle/Compiled.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE FlexibleInstances, FlexibleContexts, TypeFamilies, DerivingVia #-} {-# LANGUAGE BangPatterns, RoleAnnotations, MultiParamTypeClasses #-} {-# LANGUAGE InstanceSigs, DataKinds, TypeApplications, TypeOperators #-}-{-# LANGUAGE ConstraintKinds, PolyKinds #-}+{-# LANGUAGE ConstraintKinds, PolyKinds, UndecidableInstances #-}  -- | This module provides an implementation for the typeclasses defined in --   "Language.Souffle.Class".@@ -36,6 +36,7 @@ import Data.Foldable ( traverse_ ) import Data.Functor.Identity import Data.Proxy+import Data.Kind import qualified Data.Array as A import qualified Data.Array.IO as A import qualified Data.Array.Unsafe as A@@ -317,7 +318,7 @@  -- | A helper typeclass constraint, needed to serialize Datalog facts from --   Haskell to C++.-type Submit a = ToByteSize (Rep a)+type Submit a = ToByteSize (GetFields (Rep a))  instance MonadSouffle SouffleM where   type Handler SouffleM = Handle@@ -439,24 +440,40 @@   toByteSize = const $ Estimated 36   {-# INLINABLE toByteSize #-} -instance ToByteSize a => ToByteSize (K1 i a) where-  toByteSize = const $ toByteSize (Proxy @a)+instance ToByteSize '[] where+  toByteSize = const $ Exact 0   {-# INLINABLE toByteSize #-} -instance ToByteSize a => ToByteSize (M1 i c a) where-  toByteSize = const $ toByteSize (Proxy @a)+instance (ToByteSize a, ToByteSize as) => ToByteSize (a ': as) where+  toByteSize =+    const $ toByteSize (Proxy @a) <> toByteSize (Proxy @as)   {-# INLINABLE toByteSize #-} -instance (ToByteSize f, ToByteSize g) => ToByteSize (f :*: g) where-  toByteSize = const $-    toByteSize (Proxy @f) <> toByteSize (Proxy @g)-  {-# INLINABLE toByteSize #-}+-- | A helper type family, for getting all directly marshallable fields of a type.+type family GetFields (a :: k) :: [Type] where+  GetFields (K1 _ a) = DoGetFields a+  GetFields (M1 _ _ a) = GetFields a+  GetFields (f :*: g) = GetFields f ++ GetFields g -estimateNumBytes :: forall a. ToByteSize (Rep a) => Proxy a -> ByteSize-estimateNumBytes _ = toByteSize (Proxy @(Rep a))+type family DoGetFields (a :: Type) :: [Type] where+  DoGetFields Int32 = '[Int32]+  DoGetFields Word32 = '[Word32]+  DoGetFields Float = '[Float]+  DoGetFields String = '[String]+  DoGetFields T.Text = '[T.Text]+  DoGetFields TL.Text = '[TL.Text]+  DoGetFields TS.ShortText = '[TS.ShortText]+  DoGetFields a = GetFields (Rep a)++type family a ++ b where+  '[] ++ b = b+  (a ': as) ++ bs = a ': as ++ bs++estimateNumBytes :: forall a. Submit a => Proxy a -> ByteSize+estimateNumBytes _ = toByteSize (Proxy @(GetFields (Rep a))) {-# INLINABLE estimateNumBytes #-} -writeBytes :: forall f a. (Foldable f, Marshal a, ToByteSize (Rep a))+writeBytes :: forall f a. (Foldable f, Marshal a, Submit a)            => MVar BufData -> Ptr Internal.Relation -> f a -> IO () writeBytes bufVar relation fa = case estimateNumBytes (Proxy @a) of   Exact numBytes -> modifyMVarMasked_ bufVar $ \bufData -> do
− lib/Language/Souffle/Internal/Constraints.hs
@@ -1,70 +0,0 @@-{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, UndecidableInstances #-}---- | A helper module for generating more user friendly type errors in the form---   of custom constraints.---   This is an internal module, not meant to be used directly.-module Language.Souffle.Internal.Constraints-  ( SimpleProduct-  ) where--import Type.Errors.Pretty-import GHC.Generics-import Data.Kind-import Data.Int-import Data.Word-import qualified Data.Text as T-import qualified Data.Text.Lazy as TL-import qualified Data.Text.Short as TS----- | A helper type family used for generating a more user-friendly type error---   for incompatible types when generically deriving marshalling code for---   the 'Language.Souffle.Marshal.Marshal' typeclass.------   The __a__ type parameter is the original type, used when displaying the type error.------   A type error is returned if the passed in type is not a simple product type---   consisting of only "simple" types like Int32, Word32, Float, String, Text---   and ShortText.-type family SimpleProduct (a :: Type) :: Constraint where-  SimpleProduct a = (ProductLike a (Rep a), OnlySimpleFields a (Rep a))--type family ProductLike (t :: Type) (f :: Type -> Type) :: Constraint where-  ProductLike t (_ :*: b) = ProductLike t b-  ProductLike t (M1 _ _ a) = ProductLike t a-  ProductLike _ (K1 _ _) = ()-  ProductLike t (_ :+: _) =-    TypeError ( "Error while deriving marshalling code for type " <> t <> ":"-              % "Cannot derive sum type, only product types are supported.")-  ProductLike t U1 =-    TypeError ( "Error while deriving marshalling code for type " <> t <> ":"-              % "Cannot automatically derive code for 0 argument constructor.")-  ProductLike t V1 =-    TypeError ( "Error while deriving marshalling code for type " <> t <> ":"-              % "Cannot derive void type.")--type family OnlySimpleFields (t :: Type) (f :: Type -> Type) :: Constraint where-  OnlySimpleFields t (a :*: b) = (OnlySimpleFields t a, OnlySimpleFields t b)-  OnlySimpleFields t (a :+: b) = (OnlySimpleFields t a, OnlySimpleFields t b)-  OnlySimpleFields t (M1 _ _ a) = OnlySimpleFields t a-  OnlySimpleFields _ U1 = ()-  OnlySimpleFields _ V1 = ()-  OnlySimpleFields t k = OnlySimpleField t k--type family OnlySimpleField (a :: Type) (f :: Type -> Type) :: Constraint where-  OnlySimpleField t (M1 _ _ a) = OnlySimpleField t a-  OnlySimpleField t (K1 _ a) = DirectlyMarshallable t a--type family DirectlyMarshallable (a :: Type) (b :: Type) :: Constraint where-  DirectlyMarshallable _ T.Text = ()-  DirectlyMarshallable _ TL.Text = ()-  DirectlyMarshallable _ TS.ShortText = ()-  DirectlyMarshallable _ Int32 = ()-  DirectlyMarshallable _ Word32 = ()-  DirectlyMarshallable _ Float = ()-  DirectlyMarshallable _ String = ()-  DirectlyMarshallable t a =-    TypeError ( "Error while generating marshalling code for " <> t <> ":"-              % "Can only marshal values of Int32, Word32, Float, String, Text and ShortText directly"-             <> ", but found " <> a <> " type instead.")-
lib/Language/Souffle/Interpreted.hs view
@@ -81,7 +81,7 @@   , cfgSouffleBin   :: Maybe FilePath   , cfgFactDir      :: Maybe FilePath   , cfgOutputDir    :: Maybe FilePath-  } deriving Show+  } deriving stock Show  -- | Retrieves the default config for the interpreter. These settings can --   be overridden using record update syntax if needed.
lib/Language/Souffle/Marshal.hs view
@@ -1,6 +1,7 @@ {-# OPTIONS_GHC -Wno-redundant-constraints #-} {-# LANGUAGE FlexibleInstances, FlexibleContexts #-} {-# LANGUAGE DefaultSignatures, TypeOperators #-}+{-# LANGUAGE TypeFamilies, DataKinds, UndecidableInstances #-}  -- | This module exposes a uniform interface to marshal values --   to and from Souffle Datalog. This is done via the 'Marshal' typeclass.@@ -10,15 +11,17 @@   ( Marshal(..)   , MonadPush(..)   , MonadPop(..)+  , SimpleProduct   ) where +import Type.Errors.Pretty import GHC.Generics import Data.Int import Data.Word+import Data.Kind import qualified Data.Text as T import qualified Data.Text.Short as TS import qualified Data.Text.Lazy as TL-import qualified Language.Souffle.Internal.Constraints as C  {- | A typeclass for serializing primitive values from Haskell to Datalog. @@ -67,7 +70,9 @@ pushed/popped one by one. You need to make sure that the marshalling of values happens in the correct order or unexpected things might happen (including crashes). Pushing and popping of fields should happen in the-same order (from left to right, as defined in Datalog).+same order (from left to right, as defined in Datalog). The ordering of how+nested products are serialized is the same as when the fields of the nested+product types are inlined into the parent type.  Generic implementations for 'push' and 'pop' that perform the previously described behavior are available. This makes it possible to@@ -86,10 +91,10 @@   pop :: MonadPop m => m a    default push-    :: (Generic a, C.SimpleProduct a, GMarshal (Rep a), MonadPush m)+    :: (Generic a, SimpleProduct a, GMarshal (Rep a), MonadPush m)     => a -> m ()   default pop-    :: (Generic a, C.SimpleProduct a, GMarshal (Rep a), MonadPop m)+    :: (Generic a, SimpleProduct a, GMarshal (Rep a), MonadPop m)     => m a   push a = gpush (from a)   {-# INLINABLE push #-}@@ -161,3 +166,41 @@   {-# INLINABLE gpush #-}   gpop = M1 <$> gpop   {-# INLINABLE gpop #-}+++-- | A helper type family used for generating a more user-friendly type error+--   for incompatible types when generically deriving marshalling code for+--   the 'Language.Souffle.Marshal.Marshal' typeclass.+--+--   The __a__ type parameter is the original type, used when displaying the type error.+--+--   A type error is returned if the passed in type is not a simple product type+--   consisting of only types that implement 'Marshal'.+type family SimpleProduct (a :: Type) :: Constraint where+  SimpleProduct a = (ProductLike a (Rep a), OnlyMarshallableFields (Rep a))++type family ProductLike (t :: Type) (f :: Type -> Type) :: Constraint where+  ProductLike t (a :*: b) = (ProductLike t a, ProductLike t b)+  ProductLike t (M1 _ _ a) = ProductLike t a+  ProductLike _ (K1 _ _) = ()+  ProductLike t (_ :+: _) =+    TypeError ( "Error while deriving marshalling code for type " <> t <> ":"+              % "Cannot derive sum type, only product types are supported.")+  ProductLike t U1 =+    TypeError ( "Error while deriving marshalling code for type " <> t <> ":"+              % "Cannot automatically derive code for 0 argument constructor.")+  ProductLike t V1 =+    TypeError ( "Error while deriving marshalling code for type " <> t <> ":"+              % "Cannot derive void type.")++type family OnlyMarshallableFields (f :: Type -> Type) :: Constraint where+  OnlyMarshallableFields (a :*: b) = (OnlyMarshallableFields a, OnlyMarshallableFields b)+  OnlyMarshallableFields (a :+: b) = (OnlyMarshallableFields a, OnlyMarshallableFields b)+  OnlyMarshallableFields (M1 _ _ a) = OnlyMarshallableFields a+  OnlyMarshallableFields U1 = ()+  OnlyMarshallableFields V1 = ()+  OnlyMarshallableFields k = OnlyMarshallableField k++type family OnlyMarshallableField (f :: Type -> Type) :: Constraint where+  OnlyMarshallableField (M1 _ _ a) = OnlyMarshallableField a+  OnlyMarshallableField (K1 _ a) = Marshal a
souffle-haskell.cabal view
@@ -1,11 +1,11 @@ cabal-version: 2.2 --- This file has been generated from package.yaml by hpack version 0.34.6.+-- This file has been generated from package.yaml by hpack version 0.34.7. -- -- see: https://github.com/sol/hpack  name:           souffle-haskell-version:        3.3.0+version:        3.4.0 synopsis:       Souffle Datalog bindings for Haskell description:    Souffle Datalog bindings for Haskell. category:       Logic Programming, Foreign Binding, Bindings@@ -13,7 +13,7 @@ bug-reports:    https://github.com/luc-tielen/souffle-haskell/issues author:         Luc Tielen maintainer:     luc.tielen@gmail.com-copyright:      2020 Luc Tielen+copyright:      2022 Luc Tielen license:        MIT license-file:   LICENSE build-type:     Simple@@ -79,7 +79,6 @@       Language.Souffle.Compiled       Language.Souffle.Internal       Language.Souffle.Internal.Bindings-      Language.Souffle.Internal.Constraints       Language.Souffle.Interpreted       Language.Souffle.Marshal   other-modules:@@ -89,10 +88,12 @@   hs-source-dirs:       lib   default-extensions:-      OverloadedStrings+      DerivingStrategies+      FlexibleContexts       LambdaCase+      OverloadedStrings       ScopedTypeVariables-  ghc-options: -Wall -Weverything -Wno-safe -Wno-unsafe -Wno-implicit-prelude -Wno-missed-specializations -Wno-all-missed-specializations -Wno-missing-import-lists -Wno-type-defaults -Wno-missing-local-signatures -Wno-monomorphism-restriction -Wno-missing-deriving-strategies -Wno-prepositive-qualified-module -Wno-missing-safe-haskell-mode -optP-Wno-nonportable-include-path -fhide-source-paths -fno-show-valid-hole-fits -fno-sort-valid-hole-fits+  ghc-options: -Wall -Weverything -Wno-safe -Wno-unsafe -Wno-implicit-prelude -Wno-missed-specializations -Wno-all-missed-specializations -Wno-missing-import-lists -Wno-type-defaults -Wno-missing-local-signatures -Wno-monomorphism-restriction -Wno-prepositive-qualified-module -Wno-missing-safe-haskell-mode -optP-Wno-nonportable-include-path -fhide-source-paths -fno-show-valid-hole-fits -fno-sort-valid-hole-fits   cxx-options: -std=c++17 -Wall   include-dirs:       cbits@@ -148,14 +149,12 @@       array <=1.0     , base >=4.12 && <5     , bytestring >=0.10.10 && <1-    , containers >=0.6.2.1 && <1     , deepseq >=1.4.4 && <2     , directory >=1.3.3 && <2     , filepath >=1.4.2 && <2     , mtl >=2.0 && <3     , process >=1.6 && <2     , profunctors >=5.6.2 && <6-    , template-haskell ==2.*     , temporary >=1.3 && <2     , text >=1.0 && <2     , text-short >=0.1.3 && <1@@ -181,10 +180,12 @@   hs-source-dirs:       tests   default-extensions:-      OverloadedStrings+      DerivingStrategies+      FlexibleContexts       LambdaCase+      OverloadedStrings       ScopedTypeVariables-  ghc-options: -Wall -Weverything -Wno-safe -Wno-unsafe -Wno-implicit-prelude -Wno-missed-specializations -Wno-all-missed-specializations -Wno-missing-import-lists -Wno-type-defaults -Wno-missing-local-signatures -Wno-monomorphism-restriction -Wno-missing-deriving-strategies -Wno-prepositive-qualified-module -Wno-missing-safe-haskell-mode -optP-Wno-nonportable-include-path -fhide-source-paths -fno-show-valid-hole-fits -fno-sort-valid-hole-fits+  ghc-options: -Wall -Weverything -Wno-safe -Wno-unsafe -Wno-implicit-prelude -Wno-missed-specializations -Wno-all-missed-specializations -Wno-missing-import-lists -Wno-type-defaults -Wno-missing-local-signatures -Wno-monomorphism-restriction -Wno-prepositive-qualified-module -Wno-missing-safe-haskell-mode -optP-Wno-nonportable-include-path -fhide-source-paths -fno-show-valid-hole-fits -fno-sort-valid-hole-fits   cxx-options: -std=c++17 -D__EMBEDDED_SOUFFLE__   include-dirs:       cbits@@ -241,24 +242,15 @@   build-depends:       array <=1.0     , base >=4.12 && <5-    , bytestring >=0.10.10 && <1-    , containers >=0.6.2.1 && <1-    , deepseq >=1.4.4 && <2     , directory >=1.3.3 && <2-    , filepath >=1.4.2 && <2     , hedgehog ==1.*     , hspec >=2.6.1 && <3.0.0     , hspec-hedgehog ==0.*-    , mtl >=2.0 && <3-    , neat-interpolation ==0.*-    , process >=1.6 && <2     , profunctors >=5.6.2 && <6     , souffle-haskell-    , template-haskell ==2.*     , temporary >=1.3 && <2     , text >=1.0 && <2     , text-short >=0.1.3 && <1-    , type-errors-pretty >=0.0.1.0 && <1     , vector <=1.0   if os(darwin)     extra-libraries:@@ -275,10 +267,12 @@   hs-source-dirs:       benchmarks   default-extensions:-      OverloadedStrings+      DerivingStrategies+      FlexibleContexts       LambdaCase+      OverloadedStrings       ScopedTypeVariables-  ghc-options: -Wall -Weverything -Wno-safe -Wno-unsafe -Wno-implicit-prelude -Wno-missed-specializations -Wno-all-missed-specializations -Wno-missing-import-lists -Wno-type-defaults -Wno-missing-local-signatures -Wno-monomorphism-restriction -Wno-missing-deriving-strategies -Wno-prepositive-qualified-module -Wno-missing-safe-haskell-mode -optP-Wno-nonportable-include-path -fhide-source-paths -fno-show-valid-hole-fits -fno-sort-valid-hole-fits +RTS -N1 -RTS+  ghc-options: -Wall -Weverything -Wno-safe -Wno-unsafe -Wno-implicit-prelude -Wno-missed-specializations -Wno-all-missed-specializations -Wno-missing-import-lists -Wno-type-defaults -Wno-missing-local-signatures -Wno-monomorphism-restriction -Wno-prepositive-qualified-module -Wno-missing-safe-haskell-mode -optP-Wno-nonportable-include-path -fhide-source-paths -fno-show-valid-hole-fits -fno-sort-valid-hole-fits +RTS -N1 -RTS   cxx-options: -std=c++17 -D__EMBEDDED_SOUFFLE__ -std=c++17 -march=native   include-dirs:       cbits@@ -331,23 +325,11 @@   cxx-sources:       benchmarks/fixtures/bench.cpp   build-depends:-      array <=1.0-    , base >=4.12 && <5-    , bytestring >=0.10.10 && <1-    , containers >=0.6.2.1 && <1+      base >=4.12 && <5     , criterion     , deepseq >=1.4.4 && <2-    , directory >=1.3.3 && <2-    , filepath >=1.4.2 && <2-    , mtl >=2.0 && <3-    , process >=1.6 && <2-    , profunctors >=5.6.2 && <6     , souffle-haskell-    , template-haskell ==2.*-    , temporary >=1.3 && <2     , text >=1.0 && <2-    , text-short >=0.1.3 && <1-    , type-errors-pretty >=0.0.1.0 && <1     , vector <=1.0   if os(darwin)     extra-libraries:
tests/Test/Language/Souffle/AnalysisSpec.hs view
@@ -17,10 +17,10 @@ data Path = Path  data Edge = Edge String String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data Reachable = Reachable String String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  instance Souffle.Program Path where   type ProgramFacts Path = [Edge, Reachable]@@ -38,7 +38,7 @@ instance Souffle.Marshal Reachable  data Results = Results [Reachable] [Edge]-  deriving (Eq, Show)+  deriving stock (Eq, Show)  pathAnalysis :: Souffle.Handle Path              -> Analysis Souffle.SouffleM [Edge] [Reachable]@@ -54,7 +54,7 @@ data RoundTrip = RoundTrip  newtype StringFact = StringFact String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  instance Souffle.Program RoundTrip where   type ProgramFacts RoundTrip = '[StringFact]
tests/Test/Language/Souffle/CompiledSpec.hs view
@@ -14,10 +14,10 @@ data Path = Path  data Edge = Edge String String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data Reachable = Reachable String String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  instance Souffle.Program Path where   type ProgramFacts Path = '[Edge, Reachable]
tests/Test/Language/Souffle/InterpretedSpec.hs view
@@ -23,10 +23,10 @@ data BadPath = BadPath  data Edge = Edge String String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data Reachable = Reachable String String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  instance Souffle.Fact Edge where   type FactDirection Edge = 'Souffle.InputOutput
tests/Test/Language/Souffle/MarshalSpec.hs view
@@ -1,4 +1,3 @@- {-# LANGUAGE DeriveGeneric, TypeFamilies, DataKinds, RankNTypes #-} {-# LANGUAGE FlexibleInstances, FlexibleContexts #-} module Test.Language.Souffle.MarshalSpec@@ -29,47 +28,55 @@   data Edge = Edge String String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype EdgeUInt = EdgeUInt Word32-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype FloatValue = FloatValue Float-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data EdgeStrict = EdgeStrict !String !String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data EdgeUnpacked   = EdgeUnpacked {-# UNPACK #-} !Int32 {-# UNPACK #-} !Int32-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  type Vertex = Text type Vertex' = Text  data EdgeSynonyms = EdgeSynonyms Vertex Vertex-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data EdgeMultipleSynonyms = EdgeMultipleSynonyms Vertex Vertex'-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data EdgeMixed = EdgeMixed Text Vertex-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data EdgeRecord   = EdgeRecord   { fromNode :: Text   , toNode :: Text-  } deriving (Eq, Show, Generic)+  } deriving stock (Eq, Show, Generic)  data IntsAndStrings = IntsAndStrings Text Int32 Text-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data LargeRecord   = LargeRecord Int32 Int32 Int32 Int32-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic) +newtype NestedNewtype = NestedNewtype LargeRecord+  deriving stock (Eq, Show, Generic) +data Pair = Pair Int32 Int32+  deriving stock (Eq, Show, Generic)++data NestedRecord = NestedRecord Pair Pair+  deriving stock (Eq, Show, Generic)+ instance Marshal Edge instance Marshal EdgeUInt instance Marshal FloatValue@@ -81,30 +88,32 @@ instance Marshal EdgeRecord instance Marshal IntsAndStrings instance Marshal LargeRecord-+instance Marshal Pair+instance Marshal NestedNewtype+instance Marshal NestedRecord  data RoundTrip = RoundTrip  newtype StringFact = StringFact String-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype TextFact = TextFact T.Text-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype LazyTextFact = LazyTextFact TL.Text-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype ShortTextFact = ShortTextFact TS.ShortText-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype Int32Fact = Int32Fact Int32-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype Word32Fact = Word32Fact Word32-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype FloatFact = FloatFact Float-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  instance Souffle.Fact StringFact where   type FactDirection StringFact = 'Souffle.InputOutput@@ -134,6 +143,14 @@   type FactDirection FloatFact = 'Souffle.InputOutput   factName = const "float_fact" +instance Souffle.Fact NestedNewtype where+  type FactDirection NestedNewtype = 'Souffle.InputOutput+  factName = const "large_record"++instance Souffle.Fact NestedRecord where+  type FactDirection NestedRecord = 'Souffle.InputOutput+  factName = const "large_record"+ instance Souffle.Marshal StringFact instance Souffle.Marshal TextFact instance Souffle.Marshal LazyTextFact@@ -144,7 +161,7 @@  instance Souffle.Program RoundTrip where   type ProgramFacts RoundTrip =-    [StringFact, TextFact, LazyTextFact, ShortTextFact, Int32Fact, Word32Fact, FloatFact]+    [StringFact, TextFact, LazyTextFact, ShortTextFact, Int32Fact, Word32Fact, FloatFact, NestedNewtype, NestedRecord]   programName = const "round_trip"  type RoundTripAction@@ -159,18 +176,18 @@  data EmptyStrings a   = EmptyStrings a a Int32-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype LongStrings a   = LongStrings a-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  newtype Unicode a   = Unicode a-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  data NoStrings a = NoStrings Word32 Int32 Float-  deriving (Eq, Show, Generic)+  deriving stock (Eq, Show, Generic)  instance Souffle.Program EdgeCases where   type ProgramFacts EdgeCases =@@ -285,6 +302,25 @@           let fact = FloatFact x           FloatFact x' <- run fact           (abs (x' - x) < epsilon) === True++        it "can serialize and deserialize newtypes" $ hedgehog $ do+          a <- forAll $ Gen.int32 (Range.linear minBound maxBound)+          b <- forAll $ Gen.int32 (Range.linear minBound maxBound)+          c <- forAll $ Gen.int32 (Range.linear minBound maxBound)+          d <- forAll $ Gen.int32 (Range.linear minBound maxBound)+          let fact = NestedNewtype $ LargeRecord a b c d+          fact' <- run fact+          fact === fact'++        it "can serialize and deserialize nested product types" $ hedgehog $ do+          a <- forAll $ Gen.int32 (Range.linear minBound maxBound)+          b <- forAll $ Gen.int32 (Range.linear minBound maxBound)+          c <- forAll $ Gen.int32 (Range.linear minBound maxBound)+          d <- forAll $ Gen.int32 (Range.linear minBound maxBound)+          let fact = NestedRecord (Pair a b) (Pair c d)+          fact' <- run fact+          fact === fact'+    describe "interpreted mode" $ parallel $     roundTripTests $ \fact -> liftIO $ Interpreted.runSouffle RoundTrip $ \handle -> do
tests/fixtures/round_trip.cpp view
@@ -109,6 +109,109 @@ ind_0.printStats(o); } };+struct t_btree_iiii__0_1_2_3__1111 {+static constexpr Relation::arity_type Arity = 4;+using t_tuple = Tuple<RamDomain, 4>;+struct t_comparator_0{+ int operator()(const t_tuple& a, const t_tuple& b) const {+  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0])) ? -1 : (ramBitCast<RamSigned>(a[0]) > ramBitCast<RamSigned>(b[0])) ? 1 :((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1])) ? -1 : (ramBitCast<RamSigned>(a[1]) > ramBitCast<RamSigned>(b[1])) ? 1 :((ramBitCast<RamSigned>(a[2]) < ramBitCast<RamSigned>(b[2])) ? -1 : (ramBitCast<RamSigned>(a[2]) > ramBitCast<RamSigned>(b[2])) ? 1 :((ramBitCast<RamSigned>(a[3]) < ramBitCast<RamSigned>(b[3])) ? -1 : (ramBitCast<RamSigned>(a[3]) > ramBitCast<RamSigned>(b[3])) ? 1 :(0))));+ }+bool less(const t_tuple& a, const t_tuple& b) const {+  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0]))|| (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1]))|| (ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1])) && ((ramBitCast<RamSigned>(a[2]) < ramBitCast<RamSigned>(b[2]))|| (ramBitCast<RamSigned>(a[2]) == ramBitCast<RamSigned>(b[2])) && ((ramBitCast<RamSigned>(a[3]) < ramBitCast<RamSigned>(b[3])))));+ }+bool equal(const t_tuple& a, const t_tuple& b) const {+return (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0]))&&(ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1]))&&(ramBitCast<RamSigned>(a[2]) == ramBitCast<RamSigned>(b[2]))&&(ramBitCast<RamSigned>(a[3]) == ramBitCast<RamSigned>(b[3]));+ }+};+using t_ind_0 = btree_set<t_tuple,t_comparator_0>;+t_ind_0 ind_0;+using iterator = t_ind_0::iterator;+struct context {+t_ind_0::operation_hints hints_0_lower;+t_ind_0::operation_hints hints_0_upper;+};+context createContext() { return context(); }+bool insert(const t_tuple& t) {+context h;+return insert(t, h);+}+bool insert(const t_tuple& t, context& h) {+if (ind_0.insert(t, h.hints_0_lower)) {+return true;+} else return false;+}+bool insert(const RamDomain* ramDomain) {+RamDomain data[4];+std::copy(ramDomain, ramDomain + 4, data);+const t_tuple& tuple = reinterpret_cast<const t_tuple&>(data);+context h;+return insert(tuple, h);+}+bool insert(RamDomain a0,RamDomain a1,RamDomain a2,RamDomain a3) {+RamDomain data[4] = {a0,a1,a2,a3};+return insert(data);+}+bool contains(const t_tuple& t, context& h) const {+return ind_0.contains(t, h.hints_0_lower);+}+bool contains(const t_tuple& t) const {+context h;+return contains(t, h);+}+std::size_t size() const {+return ind_0.size();+}+iterator find(const t_tuple& t, context& h) const {+return ind_0.find(t, h.hints_0_lower);+}+iterator find(const t_tuple& t) const {+context h;+return find(t, h);+}+range<iterator> lowerUpperRange_0000(const t_tuple& /* lower */, const t_tuple& /* upper */, context& /* h */) const {+return range<iterator>(ind_0.begin(),ind_0.end());+}+range<iterator> lowerUpperRange_0000(const t_tuple& /* lower */, const t_tuple& /* upper */) const {+return range<iterator>(ind_0.begin(),ind_0.end());+}+range<t_ind_0::iterator> lowerUpperRange_1111(const t_tuple& lower, const t_tuple& upper, context& h) const {+t_comparator_0 comparator;+int cmp = comparator(lower, upper);+if (cmp == 0) {+    auto pos = ind_0.find(lower, h.hints_0_lower);+    auto fin = ind_0.end();+    if (pos != fin) {fin = pos; ++fin;}+    return make_range(pos, fin);+}+if (cmp > 0) {+    return make_range(ind_0.end(), ind_0.end());+}+return make_range(ind_0.lower_bound(lower, h.hints_0_lower), ind_0.upper_bound(upper, h.hints_0_upper));+}+range<t_ind_0::iterator> lowerUpperRange_1111(const t_tuple& lower, const t_tuple& upper) const {+context h;+return lowerUpperRange_1111(lower,upper,h);+}+bool empty() const {+return ind_0.empty();+}+std::vector<range<iterator>> partition() const {+return ind_0.getChunks(400);+}+void purge() {+ind_0.clear();+}+iterator begin() const {+return ind_0.begin();+}+iterator end() const {+return ind_0.end();+}+void printStatistics(std::ostream& o) const {+o << " arity 4 direct b-tree index 0 lex-order [0,1,2,3]\n";+ind_0.printStats(o);+}+}; struct t_btree_i__0__1 { static constexpr Relation::arity_type Arity = 1; using t_tuple = Tuple<RamDomain, 1>;@@ -332,26 +435,31 @@ // -- Table: float_fact Own<t_btree_f__0__1> rel_1_float_fact = mk<t_btree_f__0__1>(); souffle::RelationWrapper<t_btree_f__0__1> wrapper_rel_1_float_fact;+// -- Table: large_record+Own<t_btree_iiii__0_1_2_3__1111> rel_2_large_record = mk<t_btree_iiii__0_1_2_3__1111>();+souffle::RelationWrapper<t_btree_iiii__0_1_2_3__1111> wrapper_rel_2_large_record; // -- Table: number_fact-Own<t_btree_i__0__1> rel_2_number_fact = mk<t_btree_i__0__1>();-souffle::RelationWrapper<t_btree_i__0__1> wrapper_rel_2_number_fact;+Own<t_btree_i__0__1> rel_3_number_fact = mk<t_btree_i__0__1>();+souffle::RelationWrapper<t_btree_i__0__1> wrapper_rel_3_number_fact; // -- Table: string_fact-Own<t_btree_i__0__1> rel_3_string_fact = mk<t_btree_i__0__1>();-souffle::RelationWrapper<t_btree_i__0__1> wrapper_rel_3_string_fact;+Own<t_btree_i__0__1> rel_4_string_fact = mk<t_btree_i__0__1>();+souffle::RelationWrapper<t_btree_i__0__1> wrapper_rel_4_string_fact; // -- Table: unsigned_fact-Own<t_btree_u__0__1> rel_4_unsigned_fact = mk<t_btree_u__0__1>();-souffle::RelationWrapper<t_btree_u__0__1> wrapper_rel_4_unsigned_fact;+Own<t_btree_u__0__1> rel_5_unsigned_fact = mk<t_btree_u__0__1>();+souffle::RelationWrapper<t_btree_u__0__1> wrapper_rel_5_unsigned_fact; public: Sf_round_trip() : wrapper_rel_1_float_fact(0, *rel_1_float_fact, *this, "float_fact", std::array<const char *,1>{{"f:float"}}, std::array<const char *,1>{{"x"}}, 0)-, wrapper_rel_2_number_fact(1, *rel_2_number_fact, *this, "number_fact", std::array<const char *,1>{{"i:number"}}, std::array<const char *,1>{{"x"}}, 0)-, wrapper_rel_3_string_fact(2, *rel_3_string_fact, *this, "string_fact", std::array<const char *,1>{{"s:symbol"}}, std::array<const char *,1>{{"x"}}, 0)-, wrapper_rel_4_unsigned_fact(3, *rel_4_unsigned_fact, *this, "unsigned_fact", std::array<const char *,1>{{"u:unsigned"}}, std::array<const char *,1>{{"x"}}, 0)+, wrapper_rel_2_large_record(1, *rel_2_large_record, *this, "large_record", std::array<const char *,4>{{"i:number","i:number","i:number","i:number"}}, std::array<const char *,4>{{"a","b","c","d"}}, 0)+, wrapper_rel_3_number_fact(2, *rel_3_number_fact, *this, "number_fact", std::array<const char *,1>{{"i:number"}}, std::array<const char *,1>{{"x"}}, 0)+, wrapper_rel_4_string_fact(3, *rel_4_string_fact, *this, "string_fact", std::array<const char *,1>{{"s:symbol"}}, std::array<const char *,1>{{"x"}}, 0)+, wrapper_rel_5_unsigned_fact(4, *rel_5_unsigned_fact, *this, "unsigned_fact", std::array<const char *,1>{{"u:unsigned"}}, std::array<const char *,1>{{"x"}}, 0) { addRelation("float_fact", wrapper_rel_1_float_fact, true, true);-addRelation("number_fact", wrapper_rel_2_number_fact, true, true);-addRelation("string_fact", wrapper_rel_3_string_fact, true, true);-addRelation("unsigned_fact", wrapper_rel_4_unsigned_fact, true, true);+addRelation("large_record", wrapper_rel_2_large_record, true, true);+addRelation("number_fact", wrapper_rel_3_number_fact, true, true);+addRelation("string_fact", wrapper_rel_4_string_fact, true, true);+addRelation("unsigned_fact", wrapper_rel_5_unsigned_fact, true, true); } ~Sf_round_trip() { }@@ -396,6 +504,10 @@  std::vector<RamDomain> args, ret; subroutine_3(args, ret); }+{+ std::vector<RamDomain> args, ret;+subroutine_4(args, ret);+}  // -- relation hint statistics -- signalHandler->reset();@@ -411,17 +523,21 @@ if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;} IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_1_float_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);}+try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","a\tb\tc\td"},{"auxArity","0"},{"name","large_record"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 4, \"params\": [\"a\", \"b\", \"c\", \"d\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 4, \"types\": [\"i:number\", \"i:number\", \"i:number\", \"i:number\"]}}"}});+if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_2_large_record);+} catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"name","number_fact"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"i:number\"]}}"}}); if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}-IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_2_number_fact);+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_3_number_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"name","string_fact"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"s:symbol\"]}}"}}); if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}-IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_3_string_fact);+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_4_string_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"name","unsigned_fact"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"u:unsigned\"]}}"}}); if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}-IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_4_unsigned_fact);+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_5_unsigned_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} } public:@@ -430,17 +546,21 @@ if (!inputDirectoryArg.empty()) {directiveMap["fact-dir"] = inputDirectoryArg;} IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_1_float_fact); } catch (std::exception& e) {std::cerr << "Error loading float_fact data: " << e.what() << '\n';}+try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","a\tb\tc\td"},{"auxArity","0"},{"fact-dir","."},{"name","large_record"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 4, \"params\": [\"a\", \"b\", \"c\", \"d\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 4, \"types\": [\"i:number\", \"i:number\", \"i:number\", \"i:number\"]}}"}});+if (!inputDirectoryArg.empty()) {directiveMap["fact-dir"] = inputDirectoryArg;}+IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_2_large_record);+} catch (std::exception& e) {std::cerr << "Error loading large_record data: " << e.what() << '\n';} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"fact-dir","."},{"name","number_fact"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"i:number\"]}}"}}); if (!inputDirectoryArg.empty()) {directiveMap["fact-dir"] = inputDirectoryArg;}-IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_2_number_fact);+IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_3_number_fact); } catch (std::exception& e) {std::cerr << "Error loading number_fact data: " << e.what() << '\n';} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"fact-dir","."},{"name","string_fact"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"s:symbol\"]}}"}}); if (!inputDirectoryArg.empty()) {directiveMap["fact-dir"] = inputDirectoryArg;}-IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_3_string_fact);+IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_4_string_fact); } catch (std::exception& e) {std::cerr << "Error loading string_fact data: " << e.what() << '\n';} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"fact-dir","."},{"name","unsigned_fact"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"u:unsigned\"]}}"}}); if (!inputDirectoryArg.empty()) {directiveMap["fact-dir"] = inputDirectoryArg;}-IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_4_unsigned_fact);+IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_5_unsigned_fact); } catch (std::exception& e) {std::cerr << "Error loading unsigned_fact data: " << e.what() << '\n';} } public:@@ -453,21 +573,27 @@ } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout";+rwOperation["name"] = "large_record";+rwOperation["types"] = "{\"relation\": {\"arity\": 4, \"auxArity\": 0, \"types\": [\"i:number\", \"i:number\", \"i:number\", \"i:number\"]}}";+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_2_large_record);+} catch (std::exception& e) {std::cerr << e.what();exit(1);}+try {std::map<std::string, std::string> rwOperation;+rwOperation["IO"] = "stdout"; rwOperation["name"] = "number_fact"; rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"i:number\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_2_number_fact);+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_3_number_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout"; rwOperation["name"] = "string_fact"; rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"s:symbol\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_3_string_fact);+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_4_string_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout"; rwOperation["name"] = "unsigned_fact"; rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"u:unsigned\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_4_unsigned_fact);+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_5_unsigned_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} } public:@@ -480,21 +606,27 @@ } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout";+rwOperation["name"] = "large_record";+rwOperation["types"] = "{\"relation\": {\"arity\": 4, \"auxArity\": 0, \"types\": [\"i:number\", \"i:number\", \"i:number\", \"i:number\"]}}";+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_2_large_record);+} catch (std::exception& e) {std::cerr << e.what();exit(1);}+try {std::map<std::string, std::string> rwOperation;+rwOperation["IO"] = "stdout"; rwOperation["name"] = "number_fact"; rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"i:number\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_2_number_fact);+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_3_number_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout"; rwOperation["name"] = "string_fact"; rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"s:symbol\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_3_string_fact);+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_4_string_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout"; rwOperation["name"] = "unsigned_fact"; rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"u:unsigned\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_4_unsigned_fact);+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_5_unsigned_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} } public:@@ -522,6 +654,9 @@ if (name == "stratum_3") { subroutine_3(args, ret); return;}+if (name == "stratum_4") {+subroutine_4(args, ret);+return;} fatal("unknown subroutine"); } #ifdef _MSC_VER@@ -549,15 +684,35 @@ #endif // _MSC_VER void subroutine_1(const std::vector<RamDomain>& args, std::vector<RamDomain>& ret) { if (performIO) {+try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","a\tb\tc\td"},{"auxArity","0"},{"fact-dir","."},{"name","large_record"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 4, \"params\": [\"a\", \"b\", \"c\", \"d\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 4, \"types\": [\"i:number\", \"i:number\", \"i:number\", \"i:number\"]}}"}});+if (!inputDirectory.empty()) {directiveMap["fact-dir"] = inputDirectory;}+IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_2_large_record);+} catch (std::exception& e) {std::cerr << "Error loading large_record data: " << e.what() << '\n';}+}+if (performIO) {+try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","a\tb\tc\td"},{"auxArity","0"},{"name","large_record"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 4, \"params\": [\"a\", \"b\", \"c\", \"d\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 4, \"types\": [\"i:number\", \"i:number\", \"i:number\", \"i:number\"]}}"}});+if (!outputDirectory.empty()) {directiveMap["output-dir"] = outputDirectory;}+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_2_large_record);+} catch (std::exception& e) {std::cerr << e.what();exit(1);}+}+}+#ifdef _MSC_VER+#pragma warning(default: 4100)+#endif // _MSC_VER+#ifdef _MSC_VER+#pragma warning(disable: 4100)+#endif // _MSC_VER+void subroutine_2(const std::vector<RamDomain>& args, std::vector<RamDomain>& ret) {+if (performIO) { try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"fact-dir","."},{"name","number_fact"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"i:number\"]}}"}}); if (!inputDirectory.empty()) {directiveMap["fact-dir"] = inputDirectory;}-IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_2_number_fact);+IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_3_number_fact); } catch (std::exception& e) {std::cerr << "Error loading number_fact data: " << e.what() << '\n';} } if (performIO) { try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"name","number_fact"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"i:number\"]}}"}}); if (!outputDirectory.empty()) {directiveMap["output-dir"] = outputDirectory;}-IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_2_number_fact);+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_3_number_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} } }@@ -567,17 +722,17 @@ #ifdef _MSC_VER #pragma warning(disable: 4100) #endif // _MSC_VER-void subroutine_2(const std::vector<RamDomain>& args, std::vector<RamDomain>& ret) {+void subroutine_3(const std::vector<RamDomain>& args, std::vector<RamDomain>& ret) { if (performIO) { try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"fact-dir","."},{"name","string_fact"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"s:symbol\"]}}"}}); if (!inputDirectory.empty()) {directiveMap["fact-dir"] = inputDirectory;}-IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_3_string_fact);+IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_4_string_fact); } catch (std::exception& e) {std::cerr << "Error loading string_fact data: " << e.what() << '\n';} } if (performIO) { try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"name","string_fact"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"s:symbol\"]}}"}}); if (!outputDirectory.empty()) {directiveMap["output-dir"] = outputDirectory;}-IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_3_string_fact);+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_4_string_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} } }@@ -587,17 +742,17 @@ #ifdef _MSC_VER #pragma warning(disable: 4100) #endif // _MSC_VER-void subroutine_3(const std::vector<RamDomain>& args, std::vector<RamDomain>& ret) {+void subroutine_4(const std::vector<RamDomain>& args, std::vector<RamDomain>& ret) { if (performIO) { try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"fact-dir","."},{"name","unsigned_fact"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"u:unsigned\"]}}"}}); if (!inputDirectory.empty()) {directiveMap["fact-dir"] = inputDirectory;}-IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_4_unsigned_fact);+IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_5_unsigned_fact); } catch (std::exception& e) {std::cerr << "Error loading unsigned_fact data: " << e.what() << '\n';} } if (performIO) { try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"name","unsigned_fact"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"u:unsigned\"]}}"}}); if (!outputDirectory.empty()) {directiveMap["output-dir"] = outputDirectory;}-IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_4_unsigned_fact);+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_5_unsigned_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} } }