module Serialize import Prelude import Node import Lib.Common import Lib.Types import Data.SortedMap ModFile : U ModFile = (String × List TopEntry × List (String × OpDef) × List (QName × MetaEntry) × List QName) pfunc checksum uses (MkIORes) : String → IO String := `(a) => (w) => { const arr = new TextEncoder().encode(a); // djb2 hash let val = 5381 for (let i = 0; i < arr.length; i++) { val = ((val * 33) + arr[i]) | 0 } return Prelude_MkIORes(""+val, w); }` -- this was an experiment, prepping for dumping module information pfunc dumpModFile uses (MkIORes MkUnit): String → ModFile → IO Unit := `(fn,a) => (w) => { let fs = require('fs') try { let {EncFile} = require('./serializer') let enc = EncFile.encode(a) fs.writeFileSync(fn, enc) } catch (e) {} return Prelude_MkIORes(Prelude_MkUnit, w) }` -- for now, include src and use that to see if something changed dumpModule : QName → String → ModContext → M Unit dumpModule qn src mod = do let fn = "build/\{show qn}.newtmod" let csum = mod.csum let defs = listValues mod.modDefs let ops = toList mod.ctxOps let mctx = toList mod.modMetaCtx.metas let deps = mod.modDeps liftIO $ dumpModFile fn (csum,defs,ops,mctx, deps) pfunc readModFile uses (MkIORes Just Nothing): String → IO (Maybe ModFile) := `(fn) => (w) => { let fs = require('fs') try { let {DecFile} = require('./serializer') let data = fs.readFileSync(fn) let dec = DecFile.decode(data) return Prelude_MkIORes(Prelude_Just(dec), w) } catch (e) { return Prelude_MkIORes(Prelude_Nothing(), w) } }` loadModule : QName → String → M (Maybe ModContext) loadModule qn src = do let fn = "build/\{show qn}.newtmod" (Just (csum, defs, ops, mctx, deps)) <- liftIO {M} $ readModFile fn | _ => pure Nothing let ops = mapFromList ops let defs = mapFromList $ map (\ entry => (entry.name, entry)) defs -- REVIEW can we ignore those last two inside a module let mctx = MC (mapFromList mctx) Nil 0 NoCheck if csum == src then pure $ Just $ MkModCtx csum defs mctx ops deps else pure Nothing