summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorMirek Kratochvil <exa.exa@gmail.com>2022-10-15 17:28:38 +0200
committerMirek Kratochvil <exa.exa@gmail.com>2022-10-15 17:28:38 +0200
commitc45771f947cd590a8d3d0f36481583166f2b5deb (patch)
treeb9af4cc4dfbd1b72ba1628975684fe3a416b19c3 /app
parent6fa4cec10b647ee42aabf1e367ba8fa3c820cadf (diff)
downloadprlg-c45771f947cd590a8d3d0f36481583166f2b5deb.tar.gz
prlg-c45771f947cd590a8d3d0f36481583166f2b5deb.tar.bz2
attempt
Diffstat (limited to 'app')
-rw-r--r--app/Interpreter.hs55
1 files changed, 28 insertions, 27 deletions
diff --git a/app/Interpreter.hs b/app/Interpreter.hs
index 2bc14ac..9f4d94d 100644
--- a/app/Interpreter.hs
+++ b/app/Interpreter.hs
@@ -12,7 +12,10 @@ data StrTable =
data Datum
= Atom Int -- unifies a constant
| Struct (Int, Int) -- unifies a structure with arity
- deriving (Show)
+ -- | VoidVar -- unifies with anything
+ -- | LocalVar Int -- unifies with a local variable (possibly making a new one when it's not in use yet)
+ -- | Ref Int -- unifies with the referenced value on the heap (not to be used in code)
+ deriving (Show, Eq, Ord)
data Instr
= U Datum -- something unifiable
@@ -20,15 +23,16 @@ data Instr
| Goal -- we start a new goal, set up backtracking etc
| Call -- all seems okay, call the goal
| LastCall -- tail call the goal
+ | Cut -- remove all alternative clauses of the current goal
deriving (Show)
type Code = [Instr]
type Alts = [(Code, Code)] -- clauses to try and the corresponding goals to restore
-data Stk =
- Stk Alts [(Code, Alts)]
- deriving (Show) -- local backtracks (skipped on cut) + return&backtracks
+data GolAlts =
+ GA Code Alts -- goal + choicepoints
+ deriving (Show)
type Defs = M.Map (Int, Int) [Code]
@@ -36,14 +40,14 @@ data Interp =
Interp
{ defs :: Defs -- global definitions for lookup
, hed :: Code -- current head
- , gol :: Code -- current goal
- , stk :: Stk -- possible heads with stored original goal
+ , gol :: GolAlts -- current goal with local choicepoints
+ , stk :: [GolAlts] -- stack of caller GolAlts
}
deriving (Show)
prove :: Code -> Defs -> Either (Interp, String) Bool
prove g ds =
- let i0 = Interp ds g [LastCall] (Stk [] [])
+ let i0 = Interp {defs = ds, hed = g, gol = GA [LastCall] [], stk = []}
run (Left x) = x
run (Right x) = run $ proveStep Right Left x
in run (Right i0)
@@ -57,53 +61,50 @@ proveStep c f i = go i
| Just d <- defs i M.!? f = ($ d)
| otherwise = const $ ifail $ "no definition: " ++ show f
{- Backtracking: try a fallback clause, restoring goal -}
- backtrack i@Interp {stk = Stk ((s, gs):ss) sss} =
- c i {hed = s, gol = gs, stk = Stk ss sss}
+ backtrack i@Interp {gol = GA _ ((s, gs):as)} = c i {hed = s, gol = GA gs as}
{- B: no next clause, pop stack and continue backtracking at the caller -}
- backtrack i@Interp {stk = Stk [] ((g, ss):sss)} =
- backtrack i {hed = error "failed hed", gol = g, stk = Stk ss sss}
+ backtrack i@Interp {gol = GA _ [], stk = GA g ss:sss} =
+ backtrack i {hed = error "failed hed", gol = GA g ss, stk = sss}
{- B: we ran out of possibilities and there's nothing else to backtrack. No solution found. -}
- backtrack i@Interp {stk = Stk [] []} = f (Right False)
+ backtrack i@Interp {gol = GA _ [], stk = []} = f (Right False)
{- Unification -}
- go i@Interp {hed = (U a:hs), gol = (U b:gs)} -- unify constants
+ go i@Interp {hed = (U a:hs), gol = GA (U b:gs) ss} -- unify constants
= unify a b
where
- uok = c i {hed = hs, gol = gs}
+ uok = c i {hed = hs, gol = GA gs ss}
unify (Atom a) (Atom b)
| a == b = uok
unify (Struct a) (Struct b)
| a == b = uok
unify _ _ = backtrack i
{- Resolution: Final success -}
- go i@Interp {hed = [NoGoal], gol = [LastCall], stk = Stk _ []} =
+ go i@Interp {hed = [NoGoal], gol = GA [LastCall] _, stk = []} =
f (Right True)
{- R: Goal succeeded; continue at parent frame -}
go i@Interp { hed = [NoGoal]
- , gol = [LastCall]
- , stk = Stk _ ((Goal:U (Struct f):gs, ss):sss)
+ , gol = GA [LastCall] _
+ , stk = GA (Goal:U (Struct f):gs) ss:sss
} =
withDef f $ \(hs:ohs) ->
- c i {hed = hs, gol = gs, stk = Stk (map (, gs) ohs ++ ss) sss}
+ c i {hed = hs, gol = GA gs (map (, gs) ohs ++ ss), stk = sss}
{- R: Start matching next goal -}
go i@Interp { hed = [NoGoal]
- , gol = (Call:Goal:U (Struct f):gs)
- , stk = Stk ss sss
+ , gol = GA (Call:Goal:U (Struct f):gs) ss
} =
withDef f $ \(hs:ohs) ->
- c i {hed = hs, gol = gs, stk = Stk (map (, gs) ohs ++ ss) sss}
+ c i {hed = hs, gol = GA gs (map (, gs) ohs ++ ss)}
{- R: Goal head matching succeeded, make a normal call -}
go i@Interp { hed = (Goal:U (Struct f):ngs)
- , gol = (Call:gs)
- , stk = Stk ss sss
+ , gol = GA (Call:gs) ss
+ , stk = sss
} =
withDef f $ \(hs:ohs) ->
- c i {hed = hs, gol = ngs, stk = Stk (map (, ngs) ohs) ((gs, ss) : sss)}
+ c i {hed = hs, gol = GA ngs (map (, ngs) ohs), stk = GA gs ss : sss}
{- R: Successful match continued by tail call -}
go i@Interp { hed = (Goal:U (Struct f):ngs)
- , gol = [LastCall]
- , stk = Stk _ sss
+ , gol = GA [LastCall] ss
} =
withDef f $ \(hs:ohs) ->
- c i {hed = hs, gol = ngs, stk = Stk (map (, ngs) ohs) sss}
+ c i {hed = hs, gol = GA ngs (map (, ngs) ohs ++ ss)}
{- The End -}
go _ = ifail "impossible instruction combo"