Add integers
This commit is contained in:
parent
01fa10fefb
commit
09a42340fc
4 changed files with 32 additions and 24 deletions
|
|
@ -45,6 +45,7 @@ displayList t = "|" <> displayTerm t <> "]"
|
||||||
|
|
||||||
displayTerm :: Term T.Text -> T.Text
|
displayTerm :: Term T.Text -> T.Text
|
||||||
displayTerm (TVar v) = v
|
displayTerm (TVar v) = v
|
||||||
|
displayTerm (TInt i) = T.pack $ show i
|
||||||
displayTerm (TStat s) = displayStat s
|
displayTerm (TStat s) = displayStat s
|
||||||
|
|
||||||
displayTerms :: [Term T.Text] -> T.Text
|
displayTerms :: [Term T.Text] -> T.Text
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ pTermToStat :: Parser (Term T.Text) -> Parser (Stat T.Text)
|
||||||
pTermToStat p = do
|
pTermToStat p = do
|
||||||
term <- p
|
term <- p
|
||||||
case term of
|
case term of
|
||||||
(TVar _) -> fail "expected term, not variable"
|
(TVar _) -> fail "expected statement, not variable"
|
||||||
|
(TInt _) -> fail "expected statement, not integer"
|
||||||
(TStat s) -> pure s
|
(TStat s) -> pure s
|
||||||
|
|
||||||
-- | Parse a statement of the form @name(args)@.
|
-- | Parse a statement of the form @name(args)@.
|
||||||
|
|
@ -88,6 +89,7 @@ pList = do
|
||||||
pPlainTerm :: Parser (Term T.Text)
|
pPlainTerm :: Parser (Term T.Text)
|
||||||
pPlainTerm
|
pPlainTerm
|
||||||
= (TVar <$> pVarName)
|
= (TVar <$> pVarName)
|
||||||
|
<|> (TInt <$> L.signed (pure ()) L.decimal)
|
||||||
<|> (TStat <$> pPlainStat)
|
<|> (TStat <$> pPlainStat)
|
||||||
<|> try pCons
|
<|> try pCons
|
||||||
<|> pList
|
<|> pList
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
module Propa.Prolog.Types
|
module Propa.Prolog.Types
|
||||||
( Stat(..)
|
( Stat(..)
|
||||||
, Term(..)
|
, Term(..)
|
||||||
|
, tVar
|
||||||
, Def(..)
|
, Def(..)
|
||||||
, Db
|
, Db
|
||||||
) where
|
) where
|
||||||
|
|
@ -21,21 +22,29 @@ instance Traversable Stat where
|
||||||
|
|
||||||
data Term a
|
data Term a
|
||||||
= TVar a
|
= TVar a
|
||||||
|
| TInt Integer
|
||||||
| TStat (Stat a)
|
| TStat (Stat a)
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
instance Functor Term where
|
instance Functor Term where
|
||||||
fmap f (TVar a) = TVar $ f a
|
fmap f (TVar a) = TVar $ f a
|
||||||
|
fmap _ (TInt i) = TInt i
|
||||||
fmap f (TStat s) = TStat $ fmap f s
|
fmap f (TStat s) = TStat $ fmap f s
|
||||||
|
|
||||||
instance Foldable Term where
|
instance Foldable Term where
|
||||||
foldMap f (TVar a) = f a
|
foldMap f (TVar a) = f a
|
||||||
|
foldMap _ (TInt _) = mempty
|
||||||
foldMap f (TStat s) = foldMap f s
|
foldMap f (TStat s) = foldMap f s
|
||||||
|
|
||||||
instance Traversable Term where
|
instance Traversable Term where
|
||||||
traverse f (TVar a) = TVar <$> f a
|
traverse f (TVar a) = TVar <$> f a
|
||||||
|
traverse _ (TInt i) = pure $ TInt i
|
||||||
traverse f (TStat s) = TStat <$> traverse f s
|
traverse f (TStat s) = TStat <$> traverse f s
|
||||||
|
|
||||||
|
tVar :: Term a -> Maybe a
|
||||||
|
tVar (TVar v) = Just v
|
||||||
|
tVar _ = Nothing
|
||||||
|
|
||||||
data Def a = Def (Stat a) [Stat a]
|
data Def a = Def (Stat a) [Stat a]
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ module Propa.Prolog.Unify
|
||||||
( run
|
( run
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Control.Applicative
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.Foldable
|
import Data.Foldable
|
||||||
import Data.List
|
import Data.List
|
||||||
|
|
@ -21,8 +22,8 @@ import Propa.Prolog.Types
|
||||||
|
|
||||||
-- | Start at a value and follow the map's entries until the end of the chain of
|
-- | Start at a value and follow the map's entries until the end of the chain of
|
||||||
-- references.
|
-- references.
|
||||||
follow :: (Ord a) => Map.Map a a -> a -> a
|
follow :: (Ord a) => (b -> Maybe a) -> Map.Map a b -> b -> b
|
||||||
follow m v = maybe v (follow m) $ m Map.!? v
|
follow f m b = maybe b (follow f m) $ (m Map.!?) =<< f b
|
||||||
|
|
||||||
-- | Deduplicates the elements of a finite list. Doesn't preserve the order of
|
-- | Deduplicates the elements of a finite list. Doesn't preserve the order of
|
||||||
-- the elements. Doesn't work on infinite lists.
|
-- the elements. Doesn't work on infinite lists.
|
||||||
|
|
@ -34,31 +35,23 @@ deduplicate = Set.toList . Set.fromList
|
||||||
data Context = Context
|
data Context = Context
|
||||||
{ cDb :: Db T.Text
|
{ cDb :: Db T.Text
|
||||||
, cVarIdx :: Int
|
, cVarIdx :: Int
|
||||||
, cVars :: Map.Map Int Int
|
, cTerms :: Map.Map Int (Term Int)
|
||||||
, cStats :: Map.Map Int (Stat Int)
|
|
||||||
} deriving (Show)
|
} deriving (Show)
|
||||||
|
|
||||||
newContext :: [Def T.Text] -> Context
|
newContext :: [Def T.Text] -> Context
|
||||||
newContext db = Context db 0 Map.empty Map.empty
|
newContext db = Context db 0 Map.empty
|
||||||
|
|
||||||
bindVar :: Int -> Int -> UniM ()
|
bindTerm :: Int -> Term Int -> UniM ()
|
||||||
bindVar k v = modify $ \c -> c{cVars = Map.insert k v $ cVars c}
|
bindTerm k v = modify $ \c -> c{cTerms = Map.insert k v $ cTerms c}
|
||||||
|
|
||||||
bindStat :: Int -> Stat Int -> UniM ()
|
|
||||||
bindStat k s = modify $ \c -> c{cStats = Map.insert k s $ cStats c}
|
|
||||||
|
|
||||||
-- | Look up a variable, first repeatedly in the var map and then the term map.
|
-- | Look up a variable, first repeatedly in the var map and then the term map.
|
||||||
-- Returns statements unchanged.
|
-- Returns statements unchanged.
|
||||||
--
|
--
|
||||||
-- If this returns a variable, then that variable is not bound.
|
-- If this returns a variable, then that variable is not bound.
|
||||||
lookupTerm :: Term Int -> UniM (Term Int)
|
lookupTerm :: Term Int -> UniM (Term Int)
|
||||||
lookupTerm (TVar v) = do
|
lookupTerm t = do
|
||||||
c <- get
|
c <- get
|
||||||
let lastV = follow (cVars c) v
|
pure $ follow tVar (cTerms c) t
|
||||||
pure $ case cStats c Map.!? lastV of
|
|
||||||
Nothing -> TVar lastV
|
|
||||||
Just s -> TStat s
|
|
||||||
lookupTerm t@(TStat _) = pure t
|
|
||||||
|
|
||||||
-- | A simple state monad transformer over the list monad for easy backtracking.
|
-- | A simple state monad transformer over the list monad for easy backtracking.
|
||||||
-- Needs to be changed when implementing cuts.
|
-- Needs to be changed when implementing cuts.
|
||||||
|
|
@ -101,9 +94,10 @@ unifyTerm t1 t2 = do
|
||||||
t2' <- lookupTerm t2
|
t2' <- lookupTerm t2
|
||||||
case (t1', t2') of
|
case (t1', t2') of
|
||||||
(TStat s1, TStat s2) -> unifyStat s1 s2
|
(TStat s1, TStat s2) -> unifyStat s1 s2
|
||||||
(TVar v, TStat s) -> bindStat v s
|
(TInt i1, TInt i2) -> guard $ i1 == i2
|
||||||
(TStat s, TVar v) -> bindStat v s
|
(TVar v, t) -> bindTerm v t
|
||||||
(TVar v1, TVar v2) -> bindVar v1 v2 -- The order shouldn't really matter
|
(t, TVar v) -> bindTerm v t
|
||||||
|
(_, _) -> empty
|
||||||
|
|
||||||
unifyTerms :: [Term Int] -> [Term Int] -> UniM ()
|
unifyTerms :: [Term Int] -> [Term Int] -> UniM ()
|
||||||
unifyTerms t1 t2 = do
|
unifyTerms t1 t2 = do
|
||||||
|
|
@ -125,9 +119,10 @@ varNames = do
|
||||||
-- | Find a naming (Map from integer to name) for all variables in a list of
|
-- | Find a naming (Map from integer to name) for all variables in a list of
|
||||||
-- terms based on the original variable names and the variable mapping. Attempts
|
-- terms based on the original variable names and the variable mapping. Attempts
|
||||||
-- to map variables to known variables instead of a common unknown variable.
|
-- to map variables to known variables instead of a common unknown variable.
|
||||||
findVarNaming :: Map.Map T.Text Int -> Map.Map Int Int -> [Term Int] -> Map.Map Int T.Text
|
findVarNaming :: Map.Map T.Text Int -> Map.Map Int (Term Int) -> [Term Int] -> Map.Map Int T.Text
|
||||||
findVarNaming known vars terms =
|
findVarNaming known vars terms =
|
||||||
let knownLookedUp = fmap (follow vars) known
|
let knownLookedUp :: Map.Map T.Text Int
|
||||||
|
knownLookedUp = Map.mapMaybe (tVar . follow tVar vars . TVar) known
|
||||||
knownNaming = Map.fromList $ reverse $ map swap $ Map.toList knownLookedUp
|
knownNaming = Map.fromList $ reverse $ map swap $ Map.toList knownLookedUp
|
||||||
knownNames = Map.keysSet known
|
knownNames = Map.keysSet known
|
||||||
knownVars = Map.keysSet knownNaming
|
knownVars = Map.keysSet knownNaming
|
||||||
|
|
@ -142,7 +137,8 @@ resolveVars :: Term Int -> UniM (Term Int)
|
||||||
resolveVars t = do
|
resolveVars t = do
|
||||||
t2 <- lookupTerm t
|
t2 <- lookupTerm t
|
||||||
case t2 of
|
case t2 of
|
||||||
(TVar v) -> pure $ TVar v
|
(TVar v) -> pure $ TVar v
|
||||||
|
(TInt i) -> pure $ TInt i
|
||||||
(TStat (Stat name args)) -> TStat . Stat name <$> traverse resolveVars args
|
(TStat (Stat name args)) -> TStat . Stat name <$> traverse resolveVars args
|
||||||
|
|
||||||
-- | Helper type so I can resolve variables in multiple statements
|
-- | Helper type so I can resolve variables in multiple statements
|
||||||
|
|
@ -163,5 +159,5 @@ run db stats = map fst $ runStateT helper $ newContext db
|
||||||
satisfyStats $ unStats stats2
|
satisfyStats $ unStats stats2
|
||||||
tmap <- traverse (resolveVars . TVar) vmap
|
tmap <- traverse (resolveVars . TVar) vmap
|
||||||
c <- get
|
c <- get
|
||||||
let naming = findVarNaming vmap (cVars c) $ Map.elems tmap
|
let naming = findVarNaming vmap (cTerms c) $ Map.elems tmap
|
||||||
pure $ fmap (naming Map.!) <$> tmap
|
pure $ fmap (naming Map.!) <$> tmap
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue