struct structs
This commit is contained in:
		
							parent
							
								
									2f07d89043
								
							
						
					
					
						commit
						506551ab75
					
				|  | @ -12,6 +12,7 @@ import Code | ||||||
|   , InterpFn |   , InterpFn | ||||||
|   , derefHeap |   , derefHeap | ||||||
|   , heapStruct |   , heapStruct | ||||||
|  |   , newHeapVars | ||||||
|   ) |   ) | ||||||
| import qualified Compiler as Co | import qualified Compiler as Co | ||||||
| import Control.Monad.IO.Class (liftIO) | import Control.Monad.IO.Class (liftIO) | ||||||
|  | @ -20,6 +21,7 @@ import Control.Monad.Trans.State.Lazy (get, gets, modify) | ||||||
| import Data.Functor.Identity (runIdentity) | import Data.Functor.Identity (runIdentity) | ||||||
| import Data.List (intercalate) | import Data.List (intercalate) | ||||||
| import qualified Data.Map as M | import qualified Data.Map as M | ||||||
|  | import Data.Maybe (fromJust) | ||||||
| import Env (PrlgEnv(..), findAtom, findStruct, prlgError) | import Env (PrlgEnv(..), findAtom, findStruct, prlgError) | ||||||
| import qualified IR | import qualified IR | ||||||
| import Interpreter (backtrack) | import Interpreter (backtrack) | ||||||
|  | @ -149,10 +151,64 @@ call = | ||||||
|         exec addr (Struct IR.Id {IR.arity = 0, IR.str = a}) 0 |         exec addr (Struct IR.Id {IR.arity = 0, IR.str = a}) 0 | ||||||
|       _ -> prlgError "not callable" |       _ -> prlgError "not callable" | ||||||
| 
 | 
 | ||||||
|  | {- struct building -} | ||||||
| struct :: InterpFn | struct :: InterpFn | ||||||
| struct = do | struct = do | ||||||
|  |   heap <- gets (heap . cur) | ||||||
|   scope <- gets (hvar . cur) |   scope <- gets (hvar . cur) | ||||||
|   prlgError "not yet" |   case derefHeap heap <$> scope M.!? 0 of | ||||||
|  |     Just (BoundRef addr (Struct IR.Id {IR.arity = arity, IR.str = str})) -> | ||||||
|  |       structUnify arity str | ||||||
|  |     _ -> structAssemble | ||||||
|  | 
 | ||||||
|  | heapListLength listAtom heap ref = go 0 ref ref (id, fromJust . step) | ||||||
|  |   where | ||||||
|  |     nil r | ||||||
|  |       | BoundRef _ str <- derefHeap heap r = str == Atom listAtom | ||||||
|  |       | otherwise = False | ||||||
|  |     step r | ||||||
|  |       | BoundRef addr (Struct IR.Id {IR.arity = 2, IR.str = listAtom'}) <- | ||||||
|  |          derefHeap heap r | ||||||
|  |       , listAtom == listAtom' = Just (addr + 2) | ||||||
|  |       | otherwise = Nothing | ||||||
|  |     go n fast slow (f1, f2) | ||||||
|  |       | nil fast = Just n | ||||||
|  |       | Just fast' <- step fast = | ||||||
|  |         if slow == fast' | ||||||
|  |           then Nothing | ||||||
|  |           else go (n + 1) fast' (f1 slow) (f2, f1) | ||||||
|  |       | otherwise = Nothing | ||||||
|  | 
 | ||||||
|  | structAssemble :: InterpFn | ||||||
|  | structAssemble = do | ||||||
|  |   heap <- gets (heap . cur) | ||||||
|  |   scope <- gets (hvar . cur) | ||||||
|  |   case derefHeap heap <$> scope M.!? 1 of | ||||||
|  |     Just (BoundRef addr (Atom str)) -> do | ||||||
|  |       listAtom <- findAtom "[]" | ||||||
|  |       case scope M.!? 2 >>= heapListLength listAtom heap of | ||||||
|  |         Just arity -> structUnify arity str | ||||||
|  |         _ -> prlgError "struct arity unknown" | ||||||
|  |     _ -> prlgError "struct id unknown" | ||||||
|  | 
 | ||||||
|  | structUnify arity str = do | ||||||
|  |   cur <- gets cur | ||||||
|  |   let h = heap cur | ||||||
|  |       scope = hvar cur | ||||||
|  |   listAtom <- findAtom "[]" | ||||||
|  |   let hcode = map U $ maybe VoidRef HeapRef . (scope M.!?) <$> [0 .. 2] | ||||||
|  |       (h', pvars) = newHeapVars arity h | ||||||
|  |       structData = | ||||||
|  |         Struct IR.Id {IR.arity = arity, IR.str = str} : map HeapRef pvars | ||||||
|  |       paramsData = | ||||||
|  |         concatMap | ||||||
|  |           (\pv -> [Struct IR.Id {IR.arity = 2, IR.str = listAtom}, HeapRef pv]) | ||||||
|  |           pvars ++ | ||||||
|  |         [Atom listAtom] | ||||||
|  |       gcode = map U $ structData ++ [Atom str] ++ paramsData | ||||||
|  |   modify $ \s -> | ||||||
|  |     s {cur = cur {heap = h', gol = gcode ++ gol cur, hed = hcode ++ hed cur}} | ||||||
|  |   return Nothing | ||||||
| 
 | 
 | ||||||
| {- adding the builtins -} | {- adding the builtins -} | ||||||
| addOp op = modify $ \s -> s {ops = op : ops s} | addOp op = modify $ \s -> s {ops = op : ops s} | ||||||
|  |  | ||||||
							
								
								
									
										20
									
								
								app/Code.hs
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								app/Code.hs
									
									
									
									
									
								
							|  | @ -77,6 +77,7 @@ data Dereferenced | ||||||
|   = FreeRef Int |   = FreeRef Int | ||||||
|   | BoundRef Int Datum |   | BoundRef Int Datum | ||||||
|   | NoRef |   | NoRef | ||||||
|  |   deriving (Show) | ||||||
| 
 | 
 | ||||||
| -- TRICKY: HeapRefs alone must not form a cycle other than the FreeRef case. | -- TRICKY: HeapRefs alone must not form a cycle other than the FreeRef case. | ||||||
| derefHeap :: Heap -> Int -> Dereferenced | derefHeap :: Heap -> Int -> Dereferenced | ||||||
|  | @ -89,6 +90,25 @@ derefHeap h@(Heap _ hmap) x = | ||||||
|     Just x' -> BoundRef x x' |     Just x' -> BoundRef x x' | ||||||
|     _ -> NoRef |     _ -> NoRef | ||||||
| 
 | 
 | ||||||
|  | writeHeap :: Int -> Datum -> Heap -> Heap | ||||||
|  | writeHeap addr x (Heap nxt m) = Heap nxt (M.adjust (const x) addr m) | ||||||
|  | 
 | ||||||
|  | newHeapVar :: Heap -> (Heap, Int) | ||||||
|  | newHeapVar heap = head <$> newHeapVars 1 heap | ||||||
|  | 
 | ||||||
|  | newHeapVars :: Int -> Heap -> (Heap, [Int]) | ||||||
|  | newHeapVars n (Heap nxt m) = | ||||||
|  |   let addrs = [nxt + i - 1 | i <- [1 .. n]] | ||||||
|  |    in ( Heap (nxt + n) $ | ||||||
|  |         foldr (uncurry M.insert) m [(a, HeapRef a) | a <- addrs] | ||||||
|  |       , addrs) | ||||||
|  | 
 | ||||||
|  | withNewHeapStruct :: Int -> Datum -> Heap -> ([Datum] -> Heap -> a) -> a | ||||||
|  | withNewHeapStruct addr s@(Struct Id {arity = arity}) heap cont = | ||||||
|  |   let (Heap nxt' m', addrs) = newHeapVars (arity + 1) heap | ||||||
|  |       m'' = M.insert addr (HeapRef $ head addrs) . M.insert (head addrs) s $ m' | ||||||
|  |    in cont (map HeapRef $ tail addrs) (Heap nxt' m'') | ||||||
|  | 
 | ||||||
| -- TODO are we actually going to use this? | -- TODO are we actually going to use this? | ||||||
| codeStruct :: | codeStruct :: | ||||||
|      Monad m |      Monad m | ||||||
|  |  | ||||||
|  | @ -7,13 +7,15 @@ import Code | ||||||
|   , Code |   , Code | ||||||
|   , Datum(..) |   , Datum(..) | ||||||
|   , Dereferenced(..) |   , Dereferenced(..) | ||||||
|   , Heap(..) |  | ||||||
|   , Instr(..) |   , Instr(..) | ||||||
|   , Interp(..) |   , Interp(..) | ||||||
|   , InterpFn |   , InterpFn | ||||||
|   , derefHeap |   , derefHeap | ||||||
|   , emptyHeap |   , emptyHeap | ||||||
|   , emptyScope |   , emptyScope | ||||||
|  |   , newHeapVar | ||||||
|  |   , withNewHeapStruct | ||||||
|  |   , writeHeap | ||||||
|   ) |   ) | ||||||
| import qualified Control.Monad.Trans.State.Lazy as St | import qualified Control.Monad.Trans.State.Lazy as St | ||||||
| import Env (PrlgEnv) | import Env (PrlgEnv) | ||||||
|  | @ -82,23 +84,10 @@ proveStep = St.get >>= go | ||||||
|           c i {cur = cur {hed = hs, gol = gs, heap = writeHeap r x heap}} |           c i {cur = cur {hed = hs, gol = gs, heap = writeHeap r x heap}} | ||||||
|         {- heap tools -} |         {- heap tools -} | ||||||
|         deref = derefHeap heap |         deref = derefHeap heap | ||||||
|         writeHeap addr x (Heap nxt m) = Heap nxt (M.adjust (const x) addr m) |         withNewLocal (LocalRef reg) scope cont | ||||||
|         newHeapVar h = head <$> newHeapVars 1 h |  | ||||||
|         newHeapVars n (Heap nxt m) = |  | ||||||
|           let addrs = [nxt + i - 1 | i <- [1 .. n]] |  | ||||||
|            in ( Heap (nxt + n) $ |  | ||||||
|                 foldr (uncurry M.insert) m [(a, HeapRef a) | a <- addrs] |  | ||||||
|               , addrs) |  | ||||||
|         allocLocal (LocalRef reg) scope cont |  | ||||||
|           | Just addr <- scope M.!? reg = cont scope heap addr |           | Just addr <- scope M.!? reg = cont scope heap addr | ||||||
|           | (heap', addr) <- newHeapVar heap = |           | (heap', addr) <- newHeapVar heap = | ||||||
|             cont (M.insert reg addr scope) heap' addr |             cont (M.insert reg addr scope) heap' addr | ||||||
|         newHeapStruct addr s@(Struct Id {arity = arity}) cont = |  | ||||||
|           let (Heap nxt' m', addrs) = newHeapVars (arity + 1) heap |  | ||||||
|               m'' = |  | ||||||
|                 M.insert addr (HeapRef $ head addrs) . M.insert (head addrs) s $ |  | ||||||
|                 m' |  | ||||||
|            in cont (map HeapRef $ tail addrs) (Heap nxt' m'') |  | ||||||
|         {- simple cases first -} |         {- simple cases first -} | ||||||
|         unify VoidRef VoidRef = uok |         unify VoidRef VoidRef = uok | ||||||
|         unify (Atom a) (Atom b) |         unify (Atom a) (Atom b) | ||||||
|  | @ -117,7 +106,7 @@ proveStep = St.get >>= go | ||||||
|         unify VoidRef (LocalRef _) = uok |         unify VoidRef (LocalRef _) = uok | ||||||
|         {- allocate heap for LocalRefs and retry with HeapRefs -} |         {- allocate heap for LocalRefs and retry with HeapRefs -} | ||||||
|         unify lr@(LocalRef _) _ = |         unify lr@(LocalRef _) _ = | ||||||
|           allocLocal lr (hvar cur) $ \hvar' heap' addr -> |           withNewLocal lr (hvar cur) $ \hvar' heap' addr -> | ||||||
|             c |             c | ||||||
|               i |               i | ||||||
|                 { cur = |                 { cur = | ||||||
|  | @ -125,7 +114,7 @@ proveStep = St.get >>= go | ||||||
|                       {hed = U (HeapRef addr) : hs, hvar = hvar', heap = heap'} |                       {hed = U (HeapRef addr) : hs, hvar = hvar', heap = heap'} | ||||||
|                 } |                 } | ||||||
|         unify _ lr@(LocalRef _) = |         unify _ lr@(LocalRef _) = | ||||||
|           allocLocal lr (gvar cur) $ \gvar' heap' addr -> |           withNewLocal lr (gvar cur) $ \gvar' heap' addr -> | ||||||
|             c |             c | ||||||
|               i |               i | ||||||
|                 { cur = |                 { cur = | ||||||
|  | @ -142,9 +131,10 @@ proveStep = St.get >>= go | ||||||
|               case g of |               case g of | ||||||
|                 atom@(Atom _) -> setHeap hr atom |                 atom@(Atom _) -> setHeap hr atom | ||||||
|                 s@(Struct _) -> |                 s@(Struct _) -> | ||||||
|                   newHeapStruct |                   withNewHeapStruct | ||||||
|                     hr |                     hr | ||||||
|                     s |                     s | ||||||
|  |                     heap | ||||||
|                     (\nhs nheap -> |                     (\nhs nheap -> | ||||||
|                        c |                        c | ||||||
|                          i |                          i | ||||||
|  | @ -176,9 +166,10 @@ proveStep = St.get >>= go | ||||||
|               case h of |               case h of | ||||||
|                 atom@(Atom _) -> setHeap gr atom |                 atom@(Atom _) -> setHeap gr atom | ||||||
|                 s@(Struct _) -> |                 s@(Struct _) -> | ||||||
|                   newHeapStruct |                   withNewHeapStruct | ||||||
|                     gr |                     gr | ||||||
|                     s |                     s | ||||||
|  |                     heap | ||||||
|                     (\ngs nheap -> |                     (\ngs nheap -> | ||||||
|                        c |                        c | ||||||
|                          i |                          i | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue