le switch
This commit is contained in:
parent
c45771f947
commit
31c20628ea
|
@ -1,5 +1,3 @@
|
||||||
{-# LANGUAGE TupleSections #-}
|
|
||||||
|
|
||||||
module Interpreter where
|
module Interpreter where
|
||||||
|
|
||||||
import Data.Function
|
import Data.Function
|
||||||
|
@ -28,26 +26,30 @@ data Instr
|
||||||
|
|
||||||
type Code = [Instr]
|
type Code = [Instr]
|
||||||
|
|
||||||
type Alts = [(Code, Code)] -- clauses to try and the corresponding goals to restore
|
|
||||||
|
|
||||||
data GolAlts =
|
|
||||||
GA Code Alts -- goal + choicepoints
|
|
||||||
deriving (Show)
|
|
||||||
|
|
||||||
type Defs = M.Map (Int, Int) [Code]
|
type Defs = M.Map (Int, Int) [Code]
|
||||||
|
|
||||||
|
data Cho =
|
||||||
|
Cho
|
||||||
|
{ hed :: Code -- head pointer
|
||||||
|
, gol :: Code -- goal pointer
|
||||||
|
, stk :: [Code] -- remaining "and" goals
|
||||||
|
, cut :: [Cho] -- snapshot of choicepoints
|
||||||
|
}
|
||||||
|
deriving (Show)
|
||||||
|
|
||||||
data Interp =
|
data Interp =
|
||||||
Interp
|
Interp
|
||||||
{ defs :: Defs -- global definitions for lookup
|
{ defs :: Defs -- global definitions for lookup
|
||||||
, hed :: Code -- current head
|
, cur :: Cho -- the choice that is being evaluated right now
|
||||||
, gol :: GolAlts -- current goal with local choicepoints
|
, cho :: [Cho] -- remaining choice points
|
||||||
, stk :: [GolAlts] -- stack of caller GolAlts
|
|
||||||
}
|
}
|
||||||
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 {defs = ds, hed = g, gol = GA [LastCall] [], stk = []}
|
let i0 =
|
||||||
|
Interp
|
||||||
|
{defs = ds, cur = Cho {hed = g, gol = [LastCall], stk = [], cut = []}, cho = []}
|
||||||
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)
|
||||||
|
@ -57,54 +59,67 @@ proveStep :: (Interp -> a) -> (Either (Interp, String) Bool -> a) -> Interp -> a
|
||||||
proveStep c f i = go i
|
proveStep c f i = go i
|
||||||
where
|
where
|
||||||
ifail msg = f $ Left (i, msg)
|
ifail msg = f $ Left (i, msg)
|
||||||
withDef f
|
withDef fn
|
||||||
| Just d <- defs i M.!? f = ($ d)
|
| Just d <- defs i M.!? fn = ($ d)
|
||||||
| otherwise = const $ ifail $ "no definition: " ++ show f
|
| otherwise = const $ ifail $ "no definition: " ++ show fn
|
||||||
{- Backtracking: try a fallback clause, restoring goal -}
|
{- Backtracking -}
|
||||||
backtrack i@Interp {gol = GA _ ((s, gs):as)} = c i {hed = s, gol = GA gs as}
|
backtrack i@Interp {cho = chos}
|
||||||
{- B: no next clause, pop stack and continue backtracking at the caller -}
|
{- if available, restore the easiest choicepoint -}
|
||||||
backtrack i@Interp {gol = GA _ [], stk = GA g ss:sss} =
|
| (cho:chos) <- chos = c i {cur = cho, cho = chos}
|
||||||
backtrack i {hed = error "failed hed", gol = GA g ss, stk = sss}
|
{- if there's no other choice, answer no -}
|
||||||
{- B: we ran out of possibilities and there's nothing else to backtrack. No solution found. -}
|
| otherwise = f (Right False)
|
||||||
backtrack i@Interp {gol = GA _ [], stk = []} = f (Right False)
|
|
||||||
{- Unification -}
|
{- Unification -}
|
||||||
go i@Interp {hed = (U a:hs), gol = GA (U b:gs) ss} -- unify constants
|
go i@Interp {cur = cur@Cho {hed = U a:hs, gol = U b:gs}} -- unify constants
|
||||||
= unify a b
|
= unify a b
|
||||||
where
|
where
|
||||||
uok = c i {hed = hs, gol = GA gs ss}
|
uok = c i {cur = cur {hed = hs, gol = gs}}
|
||||||
unify (Atom a) (Atom b)
|
unify (Atom a) (Atom b)
|
||||||
| a == b = uok
|
| a == b = uok
|
||||||
unify (Struct a) (Struct b)
|
unify (Struct a) (Struct b)
|
||||||
| a == b = uok
|
| a == b = uok
|
||||||
unify _ _ = backtrack i
|
unify _ _ = backtrack i
|
||||||
{- Resolution: Final success -}
|
{- Resulution -}
|
||||||
go i@Interp {hed = [NoGoal], gol = GA [LastCall] _, stk = []} =
|
go i@Interp {cur = cur@Cho {hed = hed, gol = gol, stk = stk}, cho = chos}
|
||||||
f (Right True)
|
{- top-level success -}
|
||||||
{- R: Goal succeeded; continue at parent frame -}
|
| [NoGoal] <- hed
|
||||||
go i@Interp { hed = [NoGoal]
|
, [LastCall] <- gol
|
||||||
, gol = GA [LastCall] _
|
, [] <- stk = f (Right True)
|
||||||
, stk = GA (Goal:U (Struct f):gs) ss:sss
|
{- succeed and return to caller -}
|
||||||
} =
|
| [NoGoal] <- hed
|
||||||
withDef f $ \(hs:ohs) ->
|
, [LastCall] <- gol
|
||||||
c i {hed = hs, gol = GA gs (map (, gs) ohs ++ ss), stk = sss}
|
, (Goal:U (Struct fn):gs):ss <- stk =
|
||||||
{- R: Start matching next goal -}
|
withDef fn $ \(hs:ohs) ->
|
||||||
go i@Interp { hed = [NoGoal]
|
c
|
||||||
, gol = GA (Call:Goal:U (Struct f):gs) ss
|
i
|
||||||
} =
|
{ cur = cur {hed = hs, gol = gs, stk = ss}
|
||||||
withDef f $ \(hs:ohs) ->
|
, cho = [Cho oh gs ss chos | oh <- ohs] ++ chos
|
||||||
c i {hed = hs, gol = GA gs (map (, gs) ohs ++ ss)}
|
}
|
||||||
{- R: Goal head matching succeeded, make a normal call -}
|
{- start matching next goal -}
|
||||||
go i@Interp { hed = (Goal:U (Struct f):ngs)
|
| [NoGoal] <- hed
|
||||||
, gol = GA (Call:gs) ss
|
, (Call:Goal:U (Struct fn):gs) <- gol =
|
||||||
, stk = sss
|
withDef fn $ \(hs:ohs) ->
|
||||||
} =
|
c
|
||||||
withDef f $ \(hs:ohs) ->
|
i
|
||||||
c i {hed = hs, gol = GA ngs (map (, ngs) ohs), stk = GA gs ss : sss}
|
{ cur = cur {hed = hs, gol = gs}
|
||||||
|
, cho = [Cho oh gs stk chos | oh <- ohs] ++ chos
|
||||||
|
}
|
||||||
|
{- goal head matching succeeded, make a normal call -}
|
||||||
|
| (Goal:U (Struct fn):ngs) <- hed
|
||||||
|
, (Call:gs) <- gol =
|
||||||
|
withDef fn $ \(hs:ohs) ->
|
||||||
|
c
|
||||||
|
i
|
||||||
|
{ cur = cur {hed = hs, gol = ngs, stk = gs : stk}
|
||||||
|
, cho = [Cho oh ngs stk chos | oh <- ohs] ++ chos
|
||||||
|
}
|
||||||
{- R: Successful match continued by tail call -}
|
{- R: Successful match continued by tail call -}
|
||||||
go i@Interp { hed = (Goal:U (Struct f):ngs)
|
| (Goal:U (Struct fn):ngs) <- hed
|
||||||
, gol = GA [LastCall] ss
|
, [LastCall] <- gol =
|
||||||
} =
|
withDef fn $ \(hs:ohs) ->
|
||||||
withDef f $ \(hs:ohs) ->
|
c
|
||||||
c i {hed = hs, gol = GA ngs (map (, ngs) ohs ++ ss)}
|
i
|
||||||
|
{ cur = cur {hed = hs, gol = ngs}
|
||||||
|
, cho = [Cho oh ngs stk chos | oh <- ohs] ++ chos
|
||||||
|
}
|
||||||
{- The End -}
|
{- The End -}
|
||||||
go _ = ifail "impossible instruction combo"
|
go _ = ifail "impossible instruction combo"
|
||||||
|
|
Loading…
Reference in a new issue