diff --git a/lib/Language/Souffle/Experimental.hs b/lib/Language/Souffle/Experimental.hs index 73e9405..7051a2b 100644 --- a/lib/Language/Souffle/Experimental.hs +++ b/lib/Language/Souffle/Experimental.hs @@ -2,6 +2,7 @@ {-# LANGUAGE UndecidableInstances, UndecidableSuperClasses, FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, DerivingVia, ScopedTypeVariables #-} {-# LANGUAGE PolyKinds, TypeFamilyDependencies #-} +{-# LANGUAGE FunctionalDependencies, TypeApplications #-} {-# OPTIONS_GHC -Wno-redundant-constraints #-} {-| This module provides an experimental DSL for generating Souffle Datalog code, @@ -92,6 +93,7 @@ module Language.Souffle.Experimental , __ , underscore , (|-) + , (||-) , (\/) , not' -- ** Souffle operators @@ -477,6 +479,17 @@ Head name terms |- body = infixl 0 |- +(||-) + :: forall args prog. (GenVars args) + => (forall f. Fragment f 'Relation => args -> f 'Relation ()) + -> (args -> Body 'Relation ()) + -> DSL prog 'Definition () +h ||- f = do + vars <- genVars + h vars |- f vars + +infixl 0 ||- + -- | A typeclass used for generating AST fragments of Datalog code. -- The generated fragments can be further glued together using the -- various functions in this module. @@ -991,6 +1004,15 @@ accessorNames _ = case toStrings (Proxy :: Proxy (AccessorNames a)) of -- Only tuples containing up to 10 elements are currently supported. type Tuple ctx ts = TupleOf (MapType (Term ctx) ts) +class GenVars a where + genVars :: DSL prog 'Definition a + +instance GenVars (Term 'Relation a) where + genVars = var "x" + +instance (GenVars a, GenVars b) => GenVars (a, b) where + genVars = (,) <$> genVars <*> genVars + class ToTerms (ts :: [Type]) where toTerms :: Proxy ctx -> TypeInfo a ts -> Tuple ctx ts -> NonEmpty SimpleTerm diff --git a/tests/Test/Language/Souffle/ExperimentalSpec.hs b/tests/Test/Language/Souffle/ExperimentalSpec.hs index 8a45caa..2285bc7 100644 --- a/tests/Test/Language/Souffle/ExperimentalSpec.hs +++ b/tests/Test/Language/Souffle/ExperimentalSpec.hs @@ -236,9 +236,8 @@ spec = describe "Souffle DSL" $ parallel $ do let prog = do Predicate edge <- predicateFor @Edge Predicate reachable <- predicateFor @Reachable - a <- var "a" - b <- var "b" - reachable(a, b) |- edge(a, b) + reachable ||- \ (a, b) -> edge(a, b) + reachable ||- \ (a, b) -> reachable(a, b) prog ==> [text| .decl edge(t1: symbol, t2: symbol) .input edge @@ -1114,4 +1113,3 @@ spec = describe "Souffle DSL" $ parallel $ do C.run prog C.getFacts prog rs `shouldBe` [F.Reachable "b" "c", F.Reachable "a" "c", F.Reachable "a" "b"] -