feat(zig): native Arboricx bundle parser and C ABI

This commit is contained in:
2026-05-10 21:21:58 -05:00
parent 8a673e282d
commit d7a7a8134c
27 changed files with 5365 additions and 18 deletions

View File

@@ -1,6 +1,7 @@
module Main where
import ContentStore (initContentStore, loadEnvironment, resolveExportTarget)
import ContentStore (initContentStore, loadEnvironment, loadTerm, resolveExportTarget)
import System.Exit (die)
import Server (runServer)
import Eval (evalTricu, mainResult, result)
import FileEval
@@ -32,6 +33,7 @@ data TricuArgs
| Export { hash :: String, exportNameOpt :: String, outFile :: FilePath, names :: [String] }
| Import { inFile :: FilePath }
| Serve { host :: String, port :: Int }
| ExportDag { target :: String, outFile :: FilePath }
deriving (Show, Data, Typeable)
replMode :: TricuArgs
@@ -112,10 +114,21 @@ serveMode = Serve
&= explicit
&= name "server"
exportDagMode :: TricuArgs
exportDagMode = ExportDag
{ target = def &= help "Stored term name or hash to export as a DAG node table."
&= name "t" &= typ "NAME_OR_HASH"
, outFile = def &= help "Optional output file path. Defaults to stdout."
&= name "o" &= typ "FILE"
}
&= help "Export a term's Merkle DAG as a topologically-sorted node table for host embedding."
&= explicit
&= name "export-dag"
main :: IO ()
main = do
let versionStr = "tricu Evaluator and REPL " ++ showVersion version
cmdArgsParsed <- cmdArgs $ modes [replMode, evaluateMode, decodeMode, compileMode, exportMode, importMode, serveMode]
cmdArgsParsed <- cmdArgs $ modes [replMode, evaluateMode, decodeMode, compileMode, exportMode, importMode, serveMode, exportDagMode]
&= help "tricu: Exploring Tree Calculus"
&= program "tricu"
&= summary versionStr
@@ -191,6 +204,18 @@ main = do
putStrLn $ " GET /bundle/name/:name -- convenience endpoint"
putStrLn $ " Content-Type: application/vnd.arboricx.bundle"
runServer hostStr portNum
ExportDag { target = targetName, outFile = dagOutFile } -> do
conn <- initContentStore
maybeTerm <- loadTerm conn targetName
close conn
case maybeTerm of
Nothing -> die $ "Term not found: " ++ targetName
Just term -> do
let (rootIdx, nodes) = exportDag term
output = unlines $ show rootIdx : map (\(tag, refs) -> unwords (tag : map show refs)) nodes
if null dagOutFile
then putStr output
else writeFile dagOutFile output
runTricu :: String -> String
runTricu = formatT TreeCalculus . runTricuT

View File

@@ -12,6 +12,7 @@ import System.Console.CmdArgs (Data, Typeable)
import qualified Data.ByteString as BS
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.Text as T
-- Tree Calculus Types
@@ -296,3 +297,41 @@ decodeResult tc =
|| n == 9
|| n == 10
|| n == 13
-- ---------------------------------------------------------------------------
-- DAG node-table export (for host-language kernel embedding)
-- ---------------------------------------------------------------------------
-- | Export a term's Merkle DAG as a topologically-sorted node table.
-- Children appear before parents so all index references are forward.
-- Returns (root index, list of (tag, [child_indices])).
exportDag :: T -> (Int, [(String, [Int])])
exportDag term =
let (root, acc, _) = collectDag term [] Set.empty
-- acc is in reverse post-order (children first, root last)
ordered = reverse acc
idxMap = Map.fromList [(h, i) | (i, (h, _)) <- zip [0..] ordered]
rootIdx = idxMap Map.! root
lines_ = map (formatNode idxMap . snd) ordered
in (rootIdx, lines_)
where
collectDag :: T -> [(MerkleHash, Node)] -> Set.Set MerkleHash -> (MerkleHash, [(MerkleHash, Node)], Set.Set MerkleHash)
collectDag Leaf acc seen =
let h = nodeHash NLeaf
in if Set.member h seen then (h, acc, seen) else (h, (h, NLeaf) : acc, Set.insert h seen)
collectDag (Stem t) acc seen =
let (ch, acc', seen') = collectDag t acc seen
node = NStem ch
h = nodeHash node
in if Set.member h seen' then (h, acc', seen') else (h, (h, node) : acc', Set.insert h seen')
collectDag (Fork l r) acc seen =
let (lh, acc', seen') = collectDag l acc seen
(rh, acc'', seen'') = collectDag r acc' seen'
node = NFork lh rh
h = nodeHash node
in if Set.member h seen'' then (h, acc'', seen'') else (h, (h, node) : acc'', Set.insert h seen'')
formatNode :: Map.Map MerkleHash Int -> Node -> (String, [Int])
formatNode _ NLeaf = ("leaf", [])
formatNode idxMap (NStem ch) = ("stem", [idxMap Map.! ch])
formatNode idxMap (NFork l r) = ("fork", [idxMap Map.! l, idxMap Map.! r])