have a normal Stk
This commit is contained in:
parent
eb67b6b665
commit
6fa4cec10b
|
@ -26,6 +26,10 @@ type Code = [Instr]
|
||||||
|
|
||||||
type Alts = [(Code, Code)] -- clauses to try and the corresponding goals to restore
|
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
|
||||||
|
|
||||||
type Defs = M.Map (Int, Int) [Code]
|
type Defs = M.Map (Int, Int) [Code]
|
||||||
|
|
||||||
data Interp =
|
data Interp =
|
||||||
|
@ -33,13 +37,13 @@ data Interp =
|
||||||
{ defs :: Defs -- global definitions for lookup
|
{ defs :: Defs -- global definitions for lookup
|
||||||
, hed :: Code -- current head
|
, hed :: Code -- current head
|
||||||
, gol :: Code -- current goal
|
, gol :: Code -- current goal
|
||||||
, stk :: [Alts] -- possible heads with stored original goal
|
, stk :: Stk -- possible heads with stored original goal
|
||||||
}
|
}
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
prove :: Code -> Defs -> Either (Interp, String) Bool
|
prove :: Code -> Defs -> Either (Interp, String) Bool
|
||||||
prove g ds =
|
prove g ds =
|
||||||
let i0 = Interp ds g [LastCall] [[]]
|
let i0 = Interp ds g [LastCall] (Stk [] [])
|
||||||
run (Left x) = x
|
run (Left x) = x
|
||||||
run (Right x) = run $ proveStep Right Left x
|
run (Right x) = run $ proveStep Right Left x
|
||||||
in run (Right i0)
|
in run (Right i0)
|
||||||
|
@ -52,15 +56,14 @@ proveStep c f i = go i
|
||||||
withDef f
|
withDef f
|
||||||
| Just d <- defs i M.!? f = ($ d)
|
| Just d <- defs i M.!? f = ($ d)
|
||||||
| otherwise = const $ ifail $ "no definition: " ++ show f
|
| otherwise = const $ ifail $ "no definition: " ++ show f
|
||||||
{- Backtracking -}
|
{- Backtracking: try a fallback clause, restoring goal -}
|
||||||
backtrack i@Interp {stk = ((s, gs):ss):sss} -- backtrack to next clause, restoring goal
|
backtrack i@Interp {stk = Stk ((s, gs):ss) sss} =
|
||||||
= c i {hed = s, gol = gs, stk = ss : sss}
|
c i {hed = s, gol = gs, stk = Stk ss sss}
|
||||||
backtrack i@Interp {stk = []:ss@(_:_):sss} -- no next clause, pop stack and backtrack the caller clause
|
{- B: no next clause, pop stack and continue backtracking at the caller -}
|
||||||
=
|
backtrack i@Interp {stk = Stk [] ((g, ss):sss)} =
|
||||||
backtrack
|
backtrack i {hed = error "failed hed", gol = g, stk = Stk ss sss}
|
||||||
i {hed = error "failed hed", gol = error "failed gol", stk = ss : sss}
|
{- B: we ran out of possibilities and there's nothing else to backtrack. No solution found. -}
|
||||||
backtrack i@Interp {stk = [[]]} = f (Right False)
|
backtrack i@Interp {stk = Stk [] []} = f (Right False)
|
||||||
backtrack i@Interp {stk = []:[]:_} = ifail "broken stk" -- this should not happen
|
|
||||||
{- Unification -}
|
{- Unification -}
|
||||||
go i@Interp {hed = (U a:hs), gol = (U b:gs)} -- unify constants
|
go i@Interp {hed = (U a:hs), gol = (U b:gs)} -- unify constants
|
||||||
= unify a b
|
= unify a b
|
||||||
|
@ -71,33 +74,36 @@ proveStep c f i = go i
|
||||||
unify (Struct a) (Struct b)
|
unify (Struct a) (Struct b)
|
||||||
| a == b = uok
|
| a == b = uok
|
||||||
unify _ _ = backtrack i
|
unify _ _ = backtrack i
|
||||||
{- Resolution -}
|
{- Resolution: Final success -}
|
||||||
go i@Interp {hed = [NoGoal], gol = [LastCall], stk = [_]} = f (Right True) -- final success
|
go i@Interp {hed = [NoGoal], gol = [LastCall], stk = Stk _ []} =
|
||||||
|
f (Right True)
|
||||||
|
{- R: Goal succeeded; continue at parent frame -}
|
||||||
go i@Interp { hed = [NoGoal]
|
go i@Interp { hed = [NoGoal]
|
||||||
, gol = [LastCall]
|
, gol = [LastCall]
|
||||||
, stk = _:((Goal:U (Struct f):gs, _):ss):sss
|
, stk = Stk _ ((Goal:U (Struct f):gs, ss):sss)
|
||||||
} -- goal succeeded, continue with parent frame
|
} =
|
||||||
=
|
|
||||||
withDef f $ \(hs:ohs) ->
|
withDef f $ \(hs:ohs) ->
|
||||||
c i {hed = hs, gol = gs, stk = (map (, gs) ohs ++ ss) : sss}
|
c i {hed = hs, gol = gs, stk = Stk (map (, gs) ohs ++ ss) sss}
|
||||||
|
{- R: Start matching next goal -}
|
||||||
go i@Interp { hed = [NoGoal]
|
go i@Interp { hed = [NoGoal]
|
||||||
, gol = (Call:Goal:U (Struct f):gs)
|
, gol = (Call:Goal:U (Struct f):gs)
|
||||||
, stk = ss:sss
|
, stk = Stk ss sss
|
||||||
} -- next goal
|
} =
|
||||||
=
|
|
||||||
withDef f $ \(hs:ohs) ->
|
withDef f $ \(hs:ohs) ->
|
||||||
c i {hed = hs, gol = gs, stk = (map (, gs) ohs ++ ss) : sss}
|
c i {hed = hs, gol = gs, stk = Stk (map (, gs) ohs ++ ss) sss}
|
||||||
go i@Interp {hed = (Goal:U (Struct f):ngs), gol = (Call:gs), stk = ss:sss} -- normal call
|
{- 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
|
||||||
|
} =
|
||||||
withDef f $ \(hs:ohs) ->
|
withDef f $ \(hs:ohs) ->
|
||||||
c
|
c i {hed = hs, gol = ngs, stk = Stk (map (, ngs) ohs) ((gs, ss) : sss)}
|
||||||
i
|
{- R: Successful match continued by tail call -}
|
||||||
{ hed = hs
|
go i@Interp { hed = (Goal:U (Struct f):ngs)
|
||||||
, gol = ngs
|
, gol = [LastCall]
|
||||||
, stk = (map (, ngs) ohs) : ((gs, error "gol no hed") : ss) : sss
|
, stk = Stk _ sss
|
||||||
}
|
} =
|
||||||
go i@Interp {hed = (Goal:U (Struct f):ngs), gol = [LastCall], stk = _:sss} -- tail call
|
|
||||||
=
|
|
||||||
withDef f $ \(hs:ohs) ->
|
withDef f $ \(hs:ohs) ->
|
||||||
c i {hed = hs, gol = ngs, stk = map (, ngs) ohs : sss}
|
c i {hed = hs, gol = ngs, stk = Stk (map (, ngs) ohs) sss}
|
||||||
|
{- The End -}
|
||||||
go _ = ifail "impossible instruction combo"
|
go _ = ifail "impossible instruction combo"
|
||||||
|
|
Loading…
Reference in a new issue