delinting with an h

This commit is contained in:
Felix Dilke 2026-01-28 12:39:32 +00:00
parent fb2699624f
commit 5c0cc77221
3 changed files with 39 additions and 39 deletions

View File

@ -82,8 +82,8 @@ expr = factor `chainl1` addOrSub
-- └───────────────────────────────┘ -- └───────────────────────────────┘
parseExpr :: Text -> Either (ParseErrorBundle Text Void) Expr parseExpr :: Text -> Either (ParseErrorBundle Text Void) Expr
parseExpr input = parseExpr =
parse (sc *> expr <* eof) "<input>" input parse (sc *> expr <* eof) "<input>"
-- ┌───────────────────────────────┐ -- ┌───────────────────────────────┐
-- │ Helpful chainl1 alias │ -- │ Helpful chainl1 alias │

View File

@ -1,5 +1,4 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
module Datalog.DatalogParser where module Datalog.DatalogParser where
@ -10,6 +9,7 @@ import Text.Megaparsec
import Text.Megaparsec.Char import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L import qualified Text.Megaparsec.Char.Lexer as L
import Control.Monad (void) import Control.Monad (void)
import Data.Functor (($>))
-- ┌───────────────────────────────────────────────┐ -- ┌───────────────────────────────────────────────┐
-- │ Basic types │ -- │ Basic types │
@ -29,8 +29,8 @@ data Literal = Literal
, arguments :: [Term] , arguments :: [Term]
} deriving (Show, Eq) } deriving (Show, Eq)
data Head newtype Head
= HeadSingle Literal -- only case = HeadSingle Literal
deriving (Show, Eq) deriving (Show, Eq)
-- data Head -- data Head
@ -64,10 +64,11 @@ parens :: Parser a -> Parser a
parens = between (symbol "(") (symbol ")") parens = between (symbol "(") (symbol ")")
comma :: Parser () comma :: Parser ()
comma = () <$ symbol "," comma = void $ symbol ","
-- () <$ symbol ","
dot :: Parser () dot :: Parser ()
dot = () <$ symbol "." dot = void $ symbol "."
arrow :: Parser () arrow :: Parser ()
arrow = void $ symbol ":-" <|> symbol "" <|> symbol "->" arrow = void $ symbol ":-" <|> symbol "" <|> symbol "->"
@ -98,14 +99,17 @@ term = choice
-- │ Literal / atom │ -- │ Literal / atom │
-- └───────────────────────────────────────────────┘ -- └───────────────────────────────────────────────┘
literal :: Parser Literal literal :: Parser Literal
literal = do literal = do
neg <- (symbol "not" *> sc *> pure False) neg <- prefixedBy "not"
<|> (symbol "!" *> sc *> pure False) <|> prefixedBy "!"
<|> pure True <|> pure True
name <- identifier name <- identifier
args <- parens (term `sepBy` comma) <|> pure [] args <- parens (term `sepBy` comma) <|> pure []
pure $ Literal neg name args pure $ Literal neg name args where
prefixedBy op = (symbol op *> sc) $> False
-- ┌───────────────────────────────────────────────┐ -- ┌───────────────────────────────────────────────┐
-- │ Head │ -- │ Head │

View File

@ -18,10 +18,6 @@ import Data.Void
import Datalog.DatalogParser (Head (HeadSingle), Literal (..), Statement (..), Term (..), parseDatalog) import Datalog.DatalogParser (Head (HeadSingle), Literal (..), Statement (..), Term (..), parseDatalog)
import Text.Megaparsec (ParseErrorBundle) import Text.Megaparsec (ParseErrorBundle)
data Value
= ValueInt Int
| ValueSymbol String
data NaiveDatabase = NaiveDatabase data NaiveDatabase = NaiveDatabase
{ relations :: Map RelationId Relation { relations :: Map RelationId Relation
, constants :: Set Constant , constants :: Set Constant
@ -63,9 +59,19 @@ emptyDB =
, constants = Set.empty -- the Herbrand universe , constants = Set.empty -- the Herbrand universe
} }
lookupRelation :: RelationId -> Map RelationId Relation -> Int -> Set [Term] -> Relation
lookupRelation relationName relationMap newArity tuples =
case Map.lookup relationName relationMap of
Nothing -> Relation relationName newArity tuples []
Just relation ->
if _arity relation == newArity then
let newTuples = Set.union tuples $ _tuples relation
in Relation relationName newArity newTuples []
else throw $ BadArityException relationName newArity
withFacts :: [Text] -> NaiveDatabase withFacts :: [Text] -> NaiveDatabase
withFacts facts = withFacts =
foldr addFact emptyDB (extractFact <$> facts) foldr (addFact . extractFact) emptyDB
where where
extractFact :: Text -> Literal extractFact :: Text -> Literal
extractFact factText = extractFact factText =
@ -82,16 +88,6 @@ withFacts facts =
newRelationMap = Map.insert relationName newRelation relationMap newRelationMap = Map.insert relationName newRelation relationMap
newConstantSet = Set.union constantSet $ Set.fromList terms newConstantSet = Set.union constantSet $ Set.fromList terms
lookupRelation :: RelationId -> Map RelationId Relation -> Int -> Set [Term] -> Relation
lookupRelation relationName relationMap newArity tuples =
case Map.lookup relationName relationMap of
Nothing -> Relation relationName newArity tuples []
Just relation ->
if _arity relation == newArity then
let newTuples = Set.union tuples $ _tuples relation
in Relation relationName newArity newTuples []
else throw $ BadArityException relationName newArity
data BodyConstraint = BodyConstraint data BodyConstraint = BodyConstraint
{ _subRelation :: Relation { _subRelation :: Relation
, _elements :: [RuleElement] , _elements :: [RuleElement]
@ -167,7 +163,7 @@ withFactsAndRules facts = foldr (addRule . extractRule) (withFacts facts)
lookupVariable :: Text -> [Text] -> Int lookupVariable :: Text -> [Text] -> Int
lookupVariable varName variableNames = lookupVariable varName variableNames =
case (elemIndex varName) variableNames of case elemIndex varName variableNames of
Just index -> index Just index -> index
Nothing -> throw $ VariableLookupException varName variableNames Nothing -> throw $ VariableLookupException varName variableNames
@ -183,24 +179,24 @@ withFactsAndRules facts = foldr (addRule . extractRule) (withFacts facts)
context' = foldr digestBody context body context' = foldr digestBody context body
db' = _db context' db' = _db context'
relationMap = relations db' relationMap = relations db'
newRule =
RelationRule
{ headVariables = _variableNames context'
, bodyElements = toRuleBodyElement <$> _bodyConstraints context'
} where
toRuleBodyElement :: BodyConstraint -> RuleBodyElement
toRuleBodyElement (BodyConstraint subRelation elements) =
RuleBodyElement {
_subRelationId = _name subRelation
, _ruleElements = elements
}
relation' = relation' =
Relation Relation
{ _name = _name relation { _name = _name relation
, _arity = newArity , _arity = newArity
, _tuples = _tuples relation , _tuples = _tuples relation
, _rules = newRule : _rules relation , _rules = newRule : _rules relation
} } where
newRule =
RelationRule
{ headVariables = _variableNames context'
, bodyElements = toRuleBodyElement <$> _bodyConstraints context'
}
toRuleBodyElement :: BodyConstraint -> RuleBodyElement
toRuleBodyElement (BodyConstraint subRelation elements) =
RuleBodyElement {
_subRelationId = _name subRelation
, _ruleElements = elements
}
relationMap' = Map.insert relationName relation' relationMap relationMap' = Map.insert relationName relation' relationMap
constants' = constants db' constants' = constants db'
extractVariableNames :: [Term] -> [Text] extractVariableNames :: [Term] -> [Text]