From a6aff04742e004ba4205d07e1f8a6f6d502c2817 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Mon, 17 Aug 2026 21:13:49 +0100 Subject: [PATCH 01/42] checkpoint --- packages/coln-compiler/coln-compiler.cabal | 2 + .../coln-compiler/src/Coln/Backend/MIR.hs | 12 +++ packages/coln-compiler/src/Coln/Common.hs | 9 +++ .../coln-compiler/src/Coln/Core/Evaluation.hs | 4 +- .../coln-compiler/src/Coln/Core/Globals.hs | 2 +- .../coln-compiler/src/Coln/Core/Layout.hs | 34 +++++++++ .../coln-compiler/src/Coln/Core/Memoed.hs | 8 +- packages/coln-compiler/src/Coln/Core/Print.hs | 4 +- .../coln-compiler/src/Coln/Core/Readback.hs | 6 +- .../coln-compiler/src/Coln/Core/Syntax.hs | 4 +- packages/coln-compiler/src/Coln/Core/Value.hs | 4 +- .../src/Coln/Frontend/Parser/Top.hs | 1 + .../coln-compiler/src/Coln/MIR/Interpret.hs | 74 +++++++++++++++++++ packages/coln-compiler/src/Coln/MIR/Syntax.hs | 1 + packages/coln-compiler/src/Coln/MIR/Value.hs | 65 ++++++++++++++++ 15 files changed, 214 insertions(+), 16 deletions(-) create mode 100644 packages/coln-compiler/src/Coln/Backend/MIR.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Interpret.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Syntax.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Value.hs diff --git a/packages/coln-compiler/coln-compiler.cabal b/packages/coln-compiler/coln-compiler.cabal index 6ef83632..5b56d345 100644 --- a/packages/coln-compiler/coln-compiler.cabal +++ b/packages/coln-compiler/coln-compiler.cabal @@ -47,6 +47,8 @@ library Coln.Frontend.Parser Coln.Frontend.Parser.Expr Coln.Frontend.Parser.Top + Coln.MIR.Value + Coln.MIR.Interpret Coln.Report hs-source-dirs: src diff --git a/packages/coln-compiler/src/Coln/Backend/MIR.hs b/packages/coln-compiler/src/Coln/Backend/MIR.hs new file mode 100644 index 00000000..1c52618c --- /dev/null +++ b/packages/coln-compiler/src/Coln/Backend/MIR.hs @@ -0,0 +1,12 @@ +-- | MIR stands for "model intermediate representation" +-- it is for expressing *models* of theories, possibly in the context of free +-- variables which are set-level. +module Coln.Backend.MIR where + +-- If layout is Core -> MIR, then we need MIR values as well as MIR syntax. + +-- Specifically, this is because layout will have to be MIR value -> MIR syntax. + +data El + = Var BId + | diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index 3e87ed48..dae7a452 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -6,6 +6,7 @@ module Coln.Common ( module Diagnostician, module FNotation, module Data.Map, + module Data.Map.Ordered, module Data.Kind, module Data.Vector.Strict, module Data.Text, @@ -48,6 +49,8 @@ import Data.Foldable qualified as F import Data.Kind (Constraint, Type) import Data.Map (Map) import Data.Map qualified as Map +import Data.Map.Ordered (OMap) +import Data.Map.Ordered qualified as OMap import Data.Set qualified as Set import Data.String (IsString, fromString) import Data.Text (Text) @@ -89,6 +92,12 @@ unwrap Nothing = panic "should only unwrap a Just" class ElemAt a i b | a i -> b where elemAt :: a -> i -> b +instance (Ord a) => ElemAt (OMap a b) a b where + elemAt m k = case OMap.lookup k m of + Just v -> v + Nothing -> panic "no such key found in map" + + class Lookup a i b | a -> i b where lookup :: a -> i -> Maybe b diff --git a/packages/coln-compiler/src/Coln/Core/Evaluation.hs b/packages/coln-compiler/src/Coln/Core/Evaluation.hs index d5bdab05..7169e2cf 100644 --- a/packages/coln-compiler/src/Coln/Core/Evaluation.hs +++ b/packages/coln-compiler/src/Coln/Core/Evaluation.hs @@ -28,7 +28,7 @@ instance Compile S.El V.El where compile = \case S.LocalVar i -> (`elemAt` i) S.GlobalVar _ v -> const v - S.Code a -> V.emap V.Code . compile a + S.Code u a -> V.emap (V.Code u) . compile a S.App t0 t1 -> do let k0 = compile t0 let k1 = compile t1 @@ -76,7 +76,7 @@ compileEqualityType eq = do instance Compile S.Ty V.Ty where compile = \case S.U u -> const $ V.U u - S.Decode t -> do + S.Decode u t -> do let k = compile t V.ebind V.decode . k S.Function ft -> V.Function . compileFunctionType ft diff --git a/packages/coln-compiler/src/Coln/Core/Globals.hs b/packages/coln-compiler/src/Coln/Core/Globals.hs index 32eb487c..5dd0c91d 100644 --- a/packages/coln-compiler/src/Coln/Core/Globals.hs +++ b/packages/coln-compiler/src/Coln/Core/Globals.hs @@ -4,7 +4,6 @@ module Coln.Core.Globals where -import Data.Map.Ordered (OMap) import Data.Map.Ordered qualified as OMap import Coln.Common @@ -34,6 +33,7 @@ mkDefinition x ty tm m = do data Generator = Rel [Name] [S.Ty N] | Fun [Name] [S.Ty N] (S.Ty N) + | View [Name] [S.Ty N] (S.Ty N) data Realm = Realm { generators :: Trie Generator diff --git a/packages/coln-compiler/src/Coln/Core/Layout.hs b/packages/coln-compiler/src/Coln/Core/Layout.hs index 5b5b4997..2060360e 100644 --- a/packages/coln-compiler/src/Coln/Core/Layout.hs +++ b/packages/coln-compiler/src/Coln/Core/Layout.hs @@ -80,3 +80,37 @@ layout p sc a layoutTop :: RealmId -> V.Ty N -> (Trie Generator, M.El N) layoutTop x = layout BwdNil (emptyScope x) + +-- Walk through the term, and replace any conjunctive queries with lookups of +-- emitted views, which will be incrementally maintained +cache :: Path -> Scope -> V.El N -> (Trie Generator, M.El N) +cache p sc v = case v of + V.Code a -> do + let gt = Leaf (View (toList sc.names) (toList sc.ctx) (readb sc.len a)) + let a' = V.EltOf (TableName sc.realm p) (fromList $ zip (toList (sc.names)) (toList sc.bound)) + (gt, M.code (M.fromVTy sc.len a')) + V.Lam a f -> do + let x = argName sc.usedNames f + let (v, sc') = bind sc x a + let (gt, m) = cache p sc' (V.appClo f v) + let m' = M.lam sc.locals (M.fromVTy sc.len a) (S.Abs x m) + (gt, m') + V.Cons fields -> do + let go [] = ([], []) + go ((x, v) : rest) = do + let (gt, m) = cache (p :> x) sc v + let (gts, ms) = go rest + (gt : gts, m : ms) + let (gts, ms) = go (toList fields) + let m = M.cons (Dict fields.head (Vector.fromList ms)) + (Node $ Dict fields.head (Vector.fromList gts), m) + (V.Neu _; V.InitNeu _; V.Lit _) -> (Node (fromList []), M.fromVEl sc.len v) + +-- `cache` should produce an element whose behavior with respect to type-checking +-- is precisely the same as before. + +-- In other words, `cache` should only serve to *annotate* each query with extra +-- information about how to look it up. + +-- layoutDecls :: OMap Name (Definition Local) -> ([(Name, Trie Generator)], OMap Name (Definition Local)) +-- layoutDecls ds diff --git a/packages/coln-compiler/src/Coln/Core/Memoed.hs b/packages/coln-compiler/src/Coln/Core/Memoed.hs index 31117a0e..5c0270a4 100644 --- a/packages/coln-compiler/src/Coln/Core/Memoed.hs +++ b/packages/coln-compiler/src/Coln/Core/Memoed.hs @@ -24,7 +24,7 @@ type Ty = Memoed S.Ty V.Ty class Core el ty | el -> ty, ty -> el where localVar :: BId -> V.El N -> el N globalVar :: Name -> V.El N -> el N - code :: (V.HasEvaluation c) => ty c -> el c + code :: (V.HasEvaluation c) => Universe -> ty c -> el c app :: el N -> el N -> el N lam :: (V.HasEvaluation c) => V.Locals -> ty N -> S.Abs el c -> el c cons :: (V.HasEvaluation c) => Dict (el c) -> el c @@ -33,7 +33,7 @@ class Core el ty | el -> ty, ty -> el where lit :: Literal -> el N is :: el N -> el D univ :: Universe -> ty N - decode :: el N -> ty N + decode :: Universe -> el N -> ty N function :: V.Locals -> FunctionVariant -> ty N -> S.Abs ty N -> ty N record :: V.Locals -> S.RecordType ty -> ty D equality :: S.EqualityType el ty -> ty N @@ -43,7 +43,7 @@ class Core el ty | el -> ty, ty -> el where instance Core El Ty where localVar i v = M (S.LocalVar i) v globalVar x v = M (S.GlobalVar x v) v - code t = M (S.Code t.stx) (V.emap V.Code t.val) + code u t = M (S.Code u t.stx) (V.emap (V.Code u) t.val) app f x = M (S.App f.stx x.stx) (V.app f.val x.val) lam vs dom (S.Abs x body) = M @@ -60,7 +60,7 @@ instance Core El Ty where lit l = M (S.Lit l) (V.Lit l) is x = M (S.Is x.stx) (V.Become x.val) univ u = M (S.U u) (V.U u) - decode x = M (S.Decode x.stx) (V.decode x.val) + decode u x = M (S.Decode u x.stx) (V.decode x.val) function vs fv dom (S.Abs x body) = M (S.Function $ S.FunctionType fv dom.stx (S.Abs x body.stx)) diff --git a/packages/coln-compiler/src/Coln/Core/Print.hs b/packages/coln-compiler/src/Coln/Core/Print.hs index b44526a2..339789dc 100644 --- a/packages/coln-compiler/src/Coln/Core/Print.hs +++ b/packages/coln-compiler/src/Coln/Core/Print.hs @@ -47,7 +47,7 @@ instance ToNotation (El e) where toNotation xs = \case LocalVar i -> toNotation xs i GlobalVar x _ -> N.Ident x () - Code ty -> toNotation xs ty + Code _ ty -> toNotation xs ty App f t -> N.Juxt (toNotation xs f) (toNotation xs t) Lam _ (Abs x t) -> N.Infix (N.Ident x ()) (N.Keyword "=>" ()) (toNotation (xs :> x) t) @@ -72,7 +72,7 @@ nbinding x n = N.Infix (N.Ident x ()) (N.Keyword ":" ()) n instance ToNotation (Ty e) where toNotation xs = \case U u -> N.Keyword (fromString $ show $ pretty u) () - Decode t -> toNotation xs t + Decode _ t -> toNotation xs t Function f -> case f.cod of Abs x b -> N.Infix diff --git a/packages/coln-compiler/src/Coln/Core/Readback.hs b/packages/coln-compiler/src/Coln/Core/Readback.hs index 2b720af5..7fd5ce24 100644 --- a/packages/coln-compiler/src/Coln/Core/Readback.hs +++ b/packages/coln-compiler/src/Coln/Core/Readback.hs @@ -48,7 +48,7 @@ instance (V.HasEvaluation c) => Readback (V.El c) (S.El c) where readb n = \case V.Neu ne -> readb n ne.spine $ readb n ne.head V.InitNeu ne -> readb n ne.spine $ readb n ne.name - V.Code a -> S.Code (readb n a) + V.Code u a -> S.Code u (readb n a) V.Lam dom body -> S.Lam (readb n dom) $ case V.scase @c of SNominative -> readbClo n dom body SDescriptive -> readbClo n dom body @@ -94,8 +94,8 @@ instance Readback V.EqualityType (S.EqualityType S.El S.Ty) where instance (V.HasEvaluation c) => Readback (V.Ty c) (S.Ty c) where readb n = \case V.U u -> S.U u - V.Decode ne -> S.Decode $ readb n ne.spine $ readb n ne.head - V.InitDecode ne -> S.Decode $ readb n ne.spine $ readb n ne.name + V.Decode ne -> S.Decode ne.universe $ readb n ne.spine $ readb n ne.head + V.InitDecode ne -> S.Decode TheoryU $ readb n ne.spine $ readb n ne.name V.Function f -> S.Function $ readb n f V.Record r -> S.Record $ readb n r V.Eq eq -> S.Eq $ readb n eq diff --git a/packages/coln-compiler/src/Coln/Core/Syntax.hs b/packages/coln-compiler/src/Coln/Core/Syntax.hs index 813ceb0b..82c717dc 100644 --- a/packages/coln-compiler/src/Coln/Core/Syntax.hs +++ b/packages/coln-compiler/src/Coln/Core/Syntax.hs @@ -18,7 +18,7 @@ data Abs (f :: Case -> Type) (c :: Case) = Abs Name (f c) | AbsConst (f c) data El :: Case -> Type where LocalVar :: BId -> El N GlobalVar :: Name -> V.El N -> El N - Code :: Ty c -> El c + Code :: Universe -> Ty c -> El c Lam :: Ty N -> Abs El c -> El c App :: El N -> El N -> El N Cons :: Dict (El c) -> El c @@ -47,7 +47,7 @@ data EqualityType el ty = EqualityType data Ty :: Case -> Type where U :: Universe -> Ty N - Decode :: El N -> Ty N + Decode :: Universe -> El N -> Ty N Function :: FunctionType Ty -> Ty N Record :: RecordType Ty -> Ty D Eq :: EqualityType El Ty -> Ty N diff --git a/packages/coln-compiler/src/Coln/Core/Value.hs b/packages/coln-compiler/src/Coln/Core/Value.hs index d08c76ae..1c110da3 100644 --- a/packages/coln-compiler/src/Coln/Core/Value.hs +++ b/packages/coln-compiler/src/Coln/Core/Value.hs @@ -173,7 +173,7 @@ fullNeu n = BareNeutral n.name.head (composeSpines n.name.spine n.spine) data El :: Case -> Type where Neu :: Neutral -> El N InitNeu :: InitNeutral -> El N - Code :: Ty c -> El c + Code :: Universe -> Ty c -> El c Lam :: ~(Ty N) -> Clo El c -> El c Cons :: Dict (Evaluation El c) -> El c Lit :: Literal -> El N @@ -273,7 +273,7 @@ behavior = \case EltOf _ _ -> NoRules decode :: (HasEvaluation c) => El c -> Evaluation Ty c -decode (Code a) = epure a +decode (Code _ a) = epure a decode (Neu n) = do let u = case behavior n.ty of LikeU u' -> u' diff --git a/packages/coln-compiler/src/Coln/Frontend/Parser/Top.hs b/packages/coln-compiler/src/Coln/Frontend/Parser/Top.hs index 1a8e99ad..44777bc4 100644 --- a/packages/coln-compiler/src/Coln/Frontend/Parser/Top.hs +++ b/packages/coln-compiler/src/Coln/Frontend/Parser/Top.hs @@ -119,6 +119,7 @@ realm e g head def_ns = do theory <- theory_typ.elab (emptyElabEnv (contramap ElaboratorCode e) g Inductive) let (gt, root) = layoutTop x theory.val defs <- realmDecls e g theory.val root.val def_ns + let (gts, defs') = layoutDecls defs pure (x, Realm gt root.val theory.val defs) elabRealmDefinition :: ElabEnv N -> Mode -> (Typ N, Chk D) -> IO (Definition Local) diff --git a/packages/coln-compiler/src/Coln/MIR/Interpret.hs b/packages/coln-compiler/src/Coln/MIR/Interpret.hs new file mode 100644 index 00000000..194eca4f --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Interpret.hs @@ -0,0 +1,74 @@ +module Coln.MIR.Interpret where + +-- Interpret Core syntax into MIR values +import Coln.Common + +import Coln.MIR.Value qualified as MV +import Coln.Core.Syntax qualified as CS +import Coln.Core.Globals +import Coln.Core.Params +import Coln.Core.Memoed (Memoed (..)) + +-- No FunctionalDependency here, because we interpret syntax into different +-- parts! +class Interp a b where + interp :: Globals -> MV.Locals -> a -> b + +-- We need to plumb through more information about variants in the syntax. +-- +-- Universe for Code +-- FunctionVariant for Lam/App +-- Level for Cons/Proj + +-- This probably needs to also go through values. + +-- Alternatives: +-- - Coercion from TopLam and TheoryCode downward +-- +-- Arguably, the "right" way to do this is to plumb through that information. +-- Or rather... looking at the SOGAT, this information is *not* part of the syntax +-- for function/records, but *is* for universe operations. +-- Which implies that we should plumb through for Code/Decode, but not for +-- Lam/App/Cons/Proj... + +-- I guess we are, in a sense, *always* in checking mode? +-- Let's try coercion + +-- Another option: bidirectional +-- Another option: GADT + +interpAbs :: (Interp (f c) b) => Globals -> MV.Locals -> CS.Abs f c -> MV.Clo b +interpAbs g l (CS.Abs x body) = MV.Clo x (\v -> interp g (l :> v) body) +interpAbs g l (CS.AbsConst t) = MV.CloConst (interp g l t) + +appClo :: MV.Clo b -> MV.Model -> b +appClo (MV.Clo _ f) v = f v +appClo (MV.CloConst v) _ = v + +app :: MV.Top -> MV.Top -> MV.Top +app f v = case v of + MV.Model v -> case f of + MV.TopLam f -> appClo f v + MV.Model (MV.Lam f) -> MV.Model $ appClo f v + _ -> panic "expected lambda" + _ -> panic "cannot apply function to non-model value" + +instance Interp (CS.El c) MV.Top where + interp g l = \case + CS.LocalVar i -> MV.Model $ elemAt l i + CS.GlobalVar x _ -> do + let def = elemAt g.definitions x + interp g l def.body.stx + CS.Code u a -> case u of + (PropU; SetU) -> MV.Model $ MV.All $ interp g l a + TheoryU -> MV.TheoryCode $ interp g l a + CS.Lam _ abs -> MV.TopLam $ interpAbs g l abs + CS.App t0 t1 -> app (interp g l t0) (interp g l t1) + CS.Cons fields -> + + +instance Interp (CS.Ty c) MV.Ty where + interp = undefined + +instance Interp (CS.Ty c) MV.Theory where + interp = undefined diff --git a/packages/coln-compiler/src/Coln/MIR/Syntax.hs b/packages/coln-compiler/src/Coln/MIR/Syntax.hs new file mode 100644 index 00000000..2df00de6 --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Syntax.hs @@ -0,0 +1 @@ +module Coln.MIR.Syntax where diff --git a/packages/coln-compiler/src/Coln/MIR/Value.hs b/packages/coln-compiler/src/Coln/MIR/Value.hs new file mode 100644 index 00000000..b070d489 --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Value.hs @@ -0,0 +1,65 @@ +module Coln.MIR.Value where + +-- MIR consists of models in a context which only has set-level variables + +import Coln.Common +import Coln.Core.Params + +type Locals = Bwd Model + +data Clo a + = Clo Name (Model -> a) + | CloConst a + +data Shape + = RowId TableName + | Tuple (Dict Shape) + | BuiltinTy BuiltinTy + +data Neutral = Neutral + { head :: FId + , spine :: Bwd Name -- only projections + } + +data El + = Neu Neutral + | SetCons (Dict El) + | Lit Literal + | Single Ty + +data Pred + = EltOf TableName (Maybe El) [Maybe El] + | And (Dict Pred) + +data Ty = Ty + { shape :: Shape + , pred :: El -> Pred + } + +data Model + = All Ty + | Lift El + | Lam (Clo Model) + | ModelCons (Dict Model) + +data FunctionType = FunctionType + { dom :: Ty + , cod :: El -> Theory + } + +data RecordType = RecordType + { capture :: Locals + , fieldTypes :: Dict (Locals -> Theory) + } + +data Theory + = SetU + | PropU + | Elt Ty + | Function FunctionType + | Record RecordType + +data Top + = Model Model + | TheoryCode Theory + | TopLam (Clo Top) From bb4e7fb7f539268d363458fe38825ae7c374111e Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Wed, 19 Aug 2026 17:00:51 +0100 Subject: [PATCH 02/42] crazy refactor --- packages/coln-compiler/coln-compiler.cabal | 53 +++---- packages/coln-compiler/src/Coln/Common.hs | 10 ++ .../coln-compiler/src/Coln/Core/Conversion.hs | 38 ++--- .../coln-compiler/src/Coln/Core/Evaluation.hs | 21 +-- .../coln-compiler/src/Coln/Core/Globals.hs | 15 +- .../coln-compiler/src/Coln/Core/Layout.hs | 116 --------------- .../coln-compiler/src/Coln/Core/Memoed.hs | 26 ++-- packages/coln-compiler/src/Coln/Core/Print.hs | 36 ++--- .../coln-compiler/src/Coln/Core/Readback.hs | 10 +- .../coln-compiler/src/Coln/Core/Syntax.hs | 10 +- packages/coln-compiler/src/Coln/Core/Value.hs | 34 ++--- .../coln-compiler/src/Coln/MIR/Evaluation.hs | 39 ++++++ .../coln-compiler/src/Coln/MIR/Interpret.hs | 119 ++++++++-------- packages/coln-compiler/src/Coln/MIR/Layout.hs | 120 ++++++++++++++++ packages/coln-compiler/src/Coln/MIR/Memoed.hs | 43 ++++++ packages/coln-compiler/src/Coln/MIR/Params.hs | 72 ++++++++++ .../coln-compiler/src/Coln/MIR/Readback.hs | 60 ++++++++ packages/coln-compiler/src/Coln/MIR/Realm.hs | 23 +++ packages/coln-compiler/src/Coln/MIR/Syntax.hs | 35 +++++ packages/coln-compiler/src/Coln/MIR/Value.hs | 132 ++++++++++++------ packages/coln-compiler/src/Coln/SIR/Realm.hs | 34 +++++ .../coln-compiler/src/Coln/SIR/Separate.hs | 85 +++++++++++ packages/coln-compiler/src/Coln/SIR/Syntax.hs | 41 ++++++ 23 files changed, 804 insertions(+), 368 deletions(-) delete mode 100644 packages/coln-compiler/src/Coln/Core/Layout.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Evaluation.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Layout.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Memoed.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Params.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Readback.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Realm.hs create mode 100644 packages/coln-compiler/src/Coln/SIR/Realm.hs create mode 100644 packages/coln-compiler/src/Coln/SIR/Separate.hs create mode 100644 packages/coln-compiler/src/Coln/SIR/Syntax.hs diff --git a/packages/coln-compiler/coln-compiler.cabal b/packages/coln-compiler/coln-compiler.cabal index 5b56d345..958705d3 100644 --- a/packages/coln-compiler/coln-compiler.cabal +++ b/packages/coln-compiler/coln-compiler.cabal @@ -10,18 +10,17 @@ build-type: Simple library exposed-modules: - Coln.Backend.IR - Coln.Backend.Lower - Coln.Backend.TypeScript.AST - Coln.Backend.TypeScript.Assemble - Coln.Backend.TypeScript.Generate - Coln.Backend.TypeScript.Params + -- Coln.Backend.IR + -- Coln.Backend.Lower + -- Coln.Backend.TypeScript.AST + -- Coln.Backend.TypeScript.Assemble + -- Coln.Backend.TypeScript.Generate + -- Coln.Backend.TypeScript.Params Coln.Common Coln.Core Coln.Core.Conversion Coln.Core.Evaluation Coln.Core.Globals - Coln.Core.Layout Coln.Core.Memoed Coln.Core.Params Coln.Core.Print @@ -29,26 +28,32 @@ library Coln.Core.Syntax Coln.Core.Value Coln.Diagnostics - Coln.Elaborator.Coercion - Coln.Elaborator.Debug + -- Coln.Elaborator.Coercion + -- Coln.Elaborator.Debug Coln.Elaborator.Diagnostics - Coln.Elaborator.Environment - Coln.Elaborator.Judgment - Coln.Elaborator.Rules.Builtin - Coln.Elaborator.Rules.Equality - Coln.Elaborator.Rules.Function - Coln.Elaborator.Rules.Initial - Coln.Elaborator.Rules.Polarity - Coln.Elaborator.Rules.Record - Coln.Elaborator.Rules.Universe - Coln.Elaborator.Rules.Variable + -- Coln.Elaborator.Environment + -- Coln.Elaborator.Judgment + -- Coln.Elaborator.Rules.Builtin + -- Coln.Elaborator.Rules.Equality + -- Coln.Elaborator.Rules.Function + -- Coln.Elaborator.Rules.Initial + -- Coln.Elaborator.Rules.Polarity + -- Coln.Elaborator.Rules.Record + -- Coln.Elaborator.Rules.Universe + -- Coln.Elaborator.Rules.Variable Coln.Frontend.Diagnostics - Coln.Frontend.Notation - Coln.Frontend.Parser - Coln.Frontend.Parser.Expr - Coln.Frontend.Parser.Top - Coln.MIR.Value + -- Coln.Frontend.Notation + -- Coln.Frontend.Parser + -- Coln.Frontend.Parser.Expr + -- Coln.Frontend.Parser.Top Coln.MIR.Interpret + Coln.MIR.Evaluation + Coln.MIR.Params + Coln.MIR.Readback + Coln.MIR.Syntax + Coln.MIR.Value + Coln.SIR.Separate + Coln.SIR.Syntax Coln.Report hs-source-dirs: src diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index dae7a452..fcde9a48 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -37,6 +37,7 @@ module Coln.Common ( alphaNames, freshNameFor, freshNamesFor, + Match (..), mangleToDoc, mangleToString, fromShow, @@ -282,12 +283,21 @@ instance HasNames (Dict a) where instance HasNames [Name] where namesIn xs = Set.fromList xs +instance HasNames (Set.Set Name) where + namesIn = id + freshNamesFor :: (HasNames a) => a -> [Name] freshNamesFor a = flip filter alphaNames $ flip Set.notMember $ namesIn a freshNameFor :: (HasNames a) => a -> Name freshNameFor = head . freshNamesFor +-- Any +-------------------------------------------------------------------------------- + +data Match (f :: k -> Type) (g :: k -> Type) where + Pair :: f i -> g i -> Match f g + -- Misc -------------------------------------------------------------------------------- diff --git a/packages/coln-compiler/src/Coln/Core/Conversion.hs b/packages/coln-compiler/src/Coln/Core/Conversion.hs index a7184b70..b0dc0b2d 100644 --- a/packages/coln-compiler/src/Coln/Core/Conversion.hs +++ b/packages/coln-compiler/src/Coln/Core/Conversion.hs @@ -10,8 +10,8 @@ import Coln.Core.Print (prtIn) import Coln.Core.Value qualified as BN (BareNeutral (..)) import Coln.Core.Value qualified as V import Control.Applicative ((<|>)) -import Control.Monad (forM_, unless, zipWithM_) -import Data.Foldable qualified as F +import Control.Monad (forM_, unless) + import Data.Maybe (fromMaybe) import Data.Vector.Strict qualified as Vec @@ -84,11 +84,6 @@ instance DefEq (V.Ty N) where V.BuiltinTy b' -> unless (b == b') $ throwUnequalTys cs a a' $ Just "unequal builtin types" _ -> throwUnequalTys cs a a' Nothing - V.EltOf x vs -> case a' of - V.EltOf x' vs' -> do - unless (x == x') $ throwUnequalTys cs a a' $ Just "unequal table names" - zipWithM_ (defEq cs) (F.toList vs) (F.toList vs') - _ -> throwUnequalTys cs a a' Nothing instance DefEq V.Head where defEq cs h h' = case h of @@ -98,24 +93,19 @@ instance DefEq V.Head where V.GlobalVar x _ -> case h' of V.GlobalVar x' _ | x == x' -> pure () _ -> throwUnequalNeus cs (V.BareNeutral h V.Id) (V.BareNeutral h' V.Id) Nothing - V.Lookup x vs _ -> case h' of - V.Lookup x' vs' _ -> do - unless (x == x') $ throwUnequalNeus cs (V.BareNeutral h V.Id) (V.BareNeutral h' V.Id) $ Just "unequal table names" - zipWithM_ (defEq cs) (F.toList vs) (F.toList vs') -- XXX check heads? - _ -> throwUnequalNeus cs (V.BareNeutral h V.Id) (V.BareNeutral h' V.Id) Nothing instance DefEq V.BareNeutral where defEq cs n n' = case n.spine of V.Id -> case n'.spine of V.Id -> defEq cs n.head n'.head _ -> throwUnequalNeus cs n n' Nothing - V.App sq v -> case n'.spine of - V.App sq' v' -> do + V.App _ sq v -> case n'.spine of + V.App _ sq' v' -> do defEq cs (n{BN.spine = sq}) (n'{BN.spine = sq'}) defEq cs v v' _ -> throwUnequalNeus cs n n' Nothing - V.Proj sq x -> case n'.spine of - V.Proj sq' x' -> do + V.Proj _ sq x -> case n'.spine of + V.Proj _ sq' x' -> do defEq cs (n{BN.spine = sq}) (n'{BN.spine = sq'}) unless (x == x') $ throwUnequalNeus cs n n' Nothing _ -> throwUnequalNeus cs n n' Nothing @@ -131,9 +121,9 @@ instance DefEq V.InitNeutral where canon :: V.El N -> V.El N canon v@(V.Neu n) = case V.behavior n.ty of - V.LikeRecord _ -> V.Cons (V.unwrap n.expansion) + V.LikeRecord rt -> V.Cons rt.level (V.unwrap n.expansion) -- XXX is it okay to use LNil here? - V.LikeFunction f -> V.Lam f.dom $ V.Clo "x" V.LNil $ \w -> V.app v (elemAt w (BId 0)) + V.LikeFunction ft -> V.Lam ft.variant ft.dom $ V.Clo "x" V.LNil $ \w -> V.app ft.variant v (elemAt w (BId 0)) _ -> v canon v = v @@ -146,14 +136,14 @@ instance DefEq (V.El N) where V.InitNeu n -> case canon v' of V.InitNeu n' -> defEq cs n n' _ -> throwUnequalEls cs v v' Nothing - V.Code a -> case canon v' of - V.Code a' -> defEq cs a a' + V.Code _ a -> case canon v' of + V.Code _ a' -> defEq cs a a' _ -> throwUnequalEls cs v v' Nothing - V.Lam a c -> case canon v' of - V.Lam _ c' -> defEqClo cs a c c' + V.Lam _ a c -> case canon v' of + V.Lam _ _ c' -> defEqClo cs a c c' _ -> throwUnequalEls cs v v' Nothing - V.Cons d -> case canon v' of - V.Cons d' -> forM_ (Vec.zip d.values d'.values) (uncurry (defEq cs)) + V.Cons _ d -> case canon v' of + V.Cons _ d' -> forM_ (Vec.zip d.values d'.values) (uncurry (defEq cs)) _ -> throwUnequalEls cs v v' Nothing V.Lit l -> case canon v' of V.Lit l' -> unless (l == l') $ throwUnequalEls cs v v' $ Just "unequal literals" diff --git a/packages/coln-compiler/src/Coln/Core/Evaluation.hs b/packages/coln-compiler/src/Coln/Core/Evaluation.hs index 7169e2cf..335ef15a 100644 --- a/packages/coln-compiler/src/Coln/Core/Evaluation.hs +++ b/packages/coln-compiler/src/Coln/Core/Evaluation.hs @@ -29,18 +29,18 @@ instance Compile S.El V.El where S.LocalVar i -> (`elemAt` i) S.GlobalVar _ v -> const v S.Code u a -> V.emap (V.Code u) . compile a - S.App t0 t1 -> do + S.App fv t0 t1 -> do let k0 = compile t0 let k1 = compile t1 - \vs -> V.app (k0 vs) (k1 vs) - S.Lam dom abs -> do + \vs -> V.app fv (k0 vs) (k1 vs) + S.Lam fv dom abs -> do let k_dom = compile dom let k_clo = compileAbs abs - \vs -> V.epure $ V.Lam (k_dom vs) (k_clo vs) - S.Cons fields -> do + \vs -> V.epure $ V.Lam fv (k_dom vs) (k_clo vs) + S.Cons l fields -> do let k_fields = compile <$> fields - \vs -> V.epure $ V.Cons $ ($ vs) <$> k_fields - S.Proj t x -> do + \vs -> V.epure $ V.Cons l $ ($ vs) <$> k_fields + S.Proj _ t x -> do let k = compile t \vs -> V.proj (k vs) x S.Init t -> do @@ -50,10 +50,6 @@ instance Compile S.El V.El where S.Is t -> do let k = compile t V.Become . k - S.Lookup x ts a -> do - let kts = compile <$> ts - let ka = compile a - \vs -> V.tableLookup x (fmap (\kt -> kt vs) kts) (ka vs) compileFunctionType :: S.FunctionType S.Ty -> V.Locals -> V.FunctionType compileFunctionType ft = do @@ -86,6 +82,3 @@ instance Compile S.Ty V.Ty where S.IsTy a -> do let k = compile a V.Become . k - S.EltOf x ts -> do - let k = compile <$> ts - \vs -> V.EltOf x $ ($ vs) <$> k diff --git a/packages/coln-compiler/src/Coln/Core/Globals.hs b/packages/coln-compiler/src/Coln/Core/Globals.hs index 5dd0c91d..dfaeb1da 100644 --- a/packages/coln-compiler/src/Coln/Core/Globals.hs +++ b/packages/coln-compiler/src/Coln/Core/Globals.hs @@ -9,7 +9,6 @@ import Data.Map.Ordered qualified as OMap import Coln.Common import Coln.Core.Memoed qualified as M import Coln.Core.Params -import Coln.Core.Syntax qualified as S import Coln.Core.Value qualified as V -- Definitions @@ -27,24 +26,14 @@ mkDefinition x ty tm m = do let neu = V.reflect (V.GlobalVar x neu) V.Id ty (Just tm.val) Definition tm ty neu m --- Realms +-- Global environment -------------------------------------------------------------------------------- -data Generator - = Rel [Name] [S.Ty N] - | Fun [Name] [S.Ty N] (S.Ty N) - | View [Name] [S.Ty N] (S.Ty N) - data Realm = Realm - { generators :: Trie Generator - , root :: V.El N - , rootType :: V.Ty N + { rootType :: M.Ty N , realmDefinitions :: OMap Name (Definition Local) } --- Global environment --------------------------------------------------------------------------------- - data Globals = Globals { definitions :: OMap Name (Definition Global) , realms :: OMap Name Realm diff --git a/packages/coln-compiler/src/Coln/Core/Layout.hs b/packages/coln-compiler/src/Coln/Core/Layout.hs deleted file mode 100644 index 2060360e..00000000 --- a/packages/coln-compiler/src/Coln/Core/Layout.hs +++ /dev/null @@ -1,116 +0,0 @@ --- SPDX-FileCopyrightText: 2026 Coln contributors --- --- SPDX-License-Identifier: Apache-2.0 OR MIT - -module Coln.Core.Layout where - -import Data.Set (Set) -import Data.Set qualified as Set -import Data.String (fromString) -import Data.Vector.Strict qualified as Vector - -import Coln.Common -import Coln.Core.Globals -import Coln.Core.Memoed qualified as M -import Coln.Core.Params -import Coln.Core.Readback -import Coln.Core.Syntax qualified as S -import Coln.Core.Value qualified as V - --- Layout is the process of creating a realm from a theory, along with the --- universal model of that theory in the realm. - -freshenBy :: Name -> String -> Name -freshenBy (Name qual last) s = Name (qual ++ [last]) (fromString s) - -argName :: Set Name -> V.Clo a c -> Name -argName s (V.Clo x _ _) = - head $ filter (\x -> not $ Set.member x s) (x : (freshenBy x <$> alphaStrings)) -argName s (V.CloConst _) = head $ filter (\x -> not $ Set.member x s) alphaNames - -data Scope = Scope - { len :: CtxLen - , names :: Bwd Name - , ctx :: Bwd (S.Ty N) - , bound :: Bwd (V.El N) - , locals :: V.Locals - , usedNames :: Set Name - , realm :: RealmId - } - -emptyScope :: RealmId -> Scope -emptyScope = Scope 0 BwdNil BwdNil BwdNil V.LNil Set.empty - -bind :: Scope -> Name -> V.Ty N -> (V.El N, Scope) -bind sc x a = - let v = V.local (FId sc.len) a - sc' = Scope (sc.len + 1) (sc.names :> x) (sc.ctx :> readb sc.len a) (sc.bound :> v) (V.LSnoc sc.locals v) (Set.insert x sc.usedNames) sc.realm - in (v, sc') - -layout :: Path -> Scope -> V.Ty N -> (Trie Generator, M.El N) -layout p sc a - | (levelOf a).mlevel == Theory = case V.behavior a of - V.LikeFunction ft -> do - let x = argName sc.usedNames ft.cod - let (v, sc') = bind sc x ft.dom - let (gt, m) = layout p sc' (V.appClo ft.cod v) - let m' = M.lam sc.locals (M.fromVTy sc.len ft.dom) (S.Abs x m) - (gt, m') - V.LikeRecord rt -> do - let go _ [] = ([], []) - go l ((x, a) : rest) = do - let (gt, m) = layout (p :> x) sc (a l) - let (gts, ms) = go (V.LSnoc l m.val) rest - (gt : gts, m : ms) - let (gts, ms) = go rt.capture (toList rt.fieldTypes) - let m = M.cons (Dict rt.fieldTypes.head (Vector.fromList ms)) - (Node $ Dict rt.fieldTypes.head (Vector.fromList gts), m) - V.LikeU (SetU; PropU) -> do - -- TODO: layout Prop correctly - let gt = Leaf (Rel (toList sc.names) (toList sc.ctx)) - let a = V.EltOf (TableName sc.realm p) (fromList $ zip (toList sc.names) (toList sc.bound)) - (gt, M.code (M.fromVTy sc.len a)) - V.NoRules -> panic "cannot layout type with no rules" - V.LikeBuiltinTy _; V.LikeU _; V.LikeInductive _ -> panic "non-theory type" - | (levelOf a).mlevel == Set = do - let gt = Leaf (Fun (toList sc.names) (toList sc.ctx) (readb sc.len a)) - let v = V.tableLookup (TableName sc.realm p) (fromList $ zip (toList sc.names) (toList sc.bound)) a - (gt, M.fromVEl sc.len v) - | otherwise = panic "tried to layout a toplevel type" - -layoutTop :: RealmId -> V.Ty N -> (Trie Generator, M.El N) -layoutTop x = layout BwdNil (emptyScope x) - --- Walk through the term, and replace any conjunctive queries with lookups of --- emitted views, which will be incrementally maintained -cache :: Path -> Scope -> V.El N -> (Trie Generator, M.El N) -cache p sc v = case v of - V.Code a -> do - let gt = Leaf (View (toList sc.names) (toList sc.ctx) (readb sc.len a)) - let a' = V.EltOf (TableName sc.realm p) (fromList $ zip (toList (sc.names)) (toList sc.bound)) - (gt, M.code (M.fromVTy sc.len a')) - V.Lam a f -> do - let x = argName sc.usedNames f - let (v, sc') = bind sc x a - let (gt, m) = cache p sc' (V.appClo f v) - let m' = M.lam sc.locals (M.fromVTy sc.len a) (S.Abs x m) - (gt, m') - V.Cons fields -> do - let go [] = ([], []) - go ((x, v) : rest) = do - let (gt, m) = cache (p :> x) sc v - let (gts, ms) = go rest - (gt : gts, m : ms) - let (gts, ms) = go (toList fields) - let m = M.cons (Dict fields.head (Vector.fromList ms)) - (Node $ Dict fields.head (Vector.fromList gts), m) - (V.Neu _; V.InitNeu _; V.Lit _) -> (Node (fromList []), M.fromVEl sc.len v) - --- `cache` should produce an element whose behavior with respect to type-checking --- is precisely the same as before. - --- In other words, `cache` should only serve to *annotate* each query with extra --- information about how to look it up. - --- layoutDecls :: OMap Name (Definition Local) -> ([(Name, Trie Generator)], OMap Name (Definition Local)) --- layoutDecls ds diff --git a/packages/coln-compiler/src/Coln/Core/Memoed.hs b/packages/coln-compiler/src/Coln/Core/Memoed.hs index 5c0270a4..6980f58e 100644 --- a/packages/coln-compiler/src/Coln/Core/Memoed.hs +++ b/packages/coln-compiler/src/Coln/Core/Memoed.hs @@ -25,10 +25,10 @@ class Core el ty | el -> ty, ty -> el where localVar :: BId -> V.El N -> el N globalVar :: Name -> V.El N -> el N code :: (V.HasEvaluation c) => Universe -> ty c -> el c - app :: el N -> el N -> el N - lam :: (V.HasEvaluation c) => V.Locals -> ty N -> S.Abs el c -> el c - cons :: (V.HasEvaluation c) => Dict (el c) -> el c - proj :: el N -> Name -> el N + app :: FunctionVariant -> el N -> el N -> el N + lam :: (V.HasEvaluation c) => FunctionVariant -> V.Locals -> ty N -> S.Abs el c -> el c + cons :: (V.HasEvaluation c) => Level -> Dict (el c) -> el c + proj :: Level -> el N -> Name -> el N init :: ty N -> el D lit :: Literal -> el N is :: el N -> el D @@ -44,17 +44,17 @@ instance Core El Ty where localVar i v = M (S.LocalVar i) v globalVar x v = M (S.GlobalVar x v) v code u t = M (S.Code u t.stx) (V.emap (V.Code u) t.val) - app f x = M (S.App f.stx x.stx) (V.app f.val x.val) - lam vs dom (S.Abs x body) = + app fv f x = M (S.App fv f.stx x.stx) (V.app fv f.val x.val) + lam fv vs dom (S.Abs x body) = M - (S.Lam dom.stx (S.Abs x body.stx)) - (V.epure $ V.Lam dom.val (V.Clo x vs (compile body.stx))) - lam _ dom (S.AbsConst body) = + (S.Lam fv dom.stx (S.Abs x body.stx)) + (V.epure $ V.Lam fv dom.val (V.Clo x vs (compile body.stx))) + lam fv _ dom (S.AbsConst body) = M - (S.Lam dom.stx (S.AbsConst body.stx)) - (V.epure $ V.Lam dom.val (V.CloConst body.val)) - cons d = M (S.Cons $ (.stx) <$> d) (V.epure $ V.Cons $ (.val) <$> d) - proj x f = M (S.Proj x.stx f) (V.proj x.val f) + (S.Lam fv dom.stx (S.AbsConst body.stx)) + (V.epure $ V.Lam fv dom.val (V.CloConst body.val)) + cons l d = M (S.Cons l $ (.stx) <$> d) (V.epure $ V.Cons l $ (.val) <$> d) + proj l x f = M (S.Proj l x.stx f) (V.proj x.val f) init a = M (S.Init a.stx) (V.BecomeWith $ \n -> V.InitNeu (V.InitNeutral n a.val V.Id)) lit l = M (S.Lit l) (V.Lit l) diff --git a/packages/coln-compiler/src/Coln/Core/Print.hs b/packages/coln-compiler/src/Coln/Core/Print.hs index 339789dc..55e16140 100644 --- a/packages/coln-compiler/src/Coln/Core/Print.hs +++ b/packages/coln-compiler/src/Coln/Core/Print.hs @@ -48,13 +48,13 @@ instance ToNotation (El e) where LocalVar i -> toNotation xs i GlobalVar x _ -> N.Ident x () Code _ ty -> toNotation xs ty - App f t -> N.Juxt (toNotation xs f) (toNotation xs t) - Lam _ (Abs x t) -> + App _ f t -> N.Juxt (toNotation xs f) (toNotation xs t) + Lam _ _ (Abs x t) -> N.Infix (N.Ident x ()) (N.Keyword "=>" ()) (toNotation (xs :> x) t) - Lam _ (AbsConst t) -> + Lam _ _ (AbsConst t) -> N.Infix (N.Ident "_" ()) (N.Keyword "=>" ()) (toNotation xs t) - Proj t f -> N.Juxt (toNotation xs t) (N.Field f ()) - Cons d -> + Proj _ t f -> N.Juxt (toNotation xs t) (N.Field f ()) + Cons _ d -> N.Tuple [field y t | (y, t) <- toList d] () where field y t = N.Infix (N.Ident y ()) (N.Keyword ":=" ()) (toNotation xs t) @@ -62,9 +62,6 @@ instance ToNotation (El e) where Lit (LitInt i) -> N.Int i () Lit (LitString s) -> N.String s () Is t -> toNotation xs t -- invisible - Lookup x ts _ -> N.Juxt (toNotation xs x) (N.Tuple (field <$> toList ts) ()) - where - field (y, t) = N.Infix (N.Ident y ()) (N.Keyword ":=" ()) (toNotation xs t) nbinding :: Name -> N.Ntn0 -> N.Ntn0 nbinding x n = N.Infix (N.Ident x ()) (N.Keyword ":" ()) n @@ -96,9 +93,6 @@ instance ToNotation (Ty e) where (toNotation xs eq.rhs) BuiltinTy a -> N.Keyword (fromString $ show a) () IsTy a -> toNotation xs a - EltOf x ts -> N.Juxt (toNotation xs x) (N.Tuple (field <$> toList ts) ()) - where - field (y, t) = N.Infix (N.Ident y ()) (N.Keyword ":=" ()) (toNotation xs t) instance ToNotation TypeBehavior where toNotation xs = \case @@ -118,14 +112,14 @@ toNotationTele xs tys = go xs BwdNil tys bnd : go xs' (names :> x) tys' go _ _ _ = panic "mismatched lengths" -instance ToNotationTop Generator where - toNotationTop (Rel xs tys) = - N.Juxt (N.Keyword "rel" ()) (N.Tuple (toNotationTele xs tys) ()) - toNotationTop (Fun xs tys ret) = - N.Infix - (N.Juxt (N.Keyword "fun" ()) (N.Tuple (toNotationTele xs tys) ())) - (N.Keyword "->" ()) - (toNotation (fromList xs) ret) +-- instance ToNotationTop Generator where +-- toNotationTop (Rel xs tys) = +-- N.Juxt (N.Keyword "rel" ()) (N.Tuple (toNotationTele xs tys) ()) +-- toNotationTop (Fun xs tys ret) = +-- N.Infix +-- (N.Juxt (N.Keyword "fun" ()) (N.Tuple (toNotationTele xs tys) ())) +-- (N.Keyword "->" ()) +-- (toNotation (fromList xs) ret) instance (ToNotationTop a) => ToNotationTop (Trie a) where toNotationTop (Leaf g) = toNotationTop g @@ -141,9 +135,7 @@ instance ToNotationTop Realm where N.Block "realm" Nothing - [ N.Block "generators" Nothing [toNotationTop r.generators] () - , N.Block "definitions" Nothing (go (BwdNil :> "root") (OMap.assocs r.realmDefinitions)) () - ] + (go (BwdNil :> "root") (OMap.assocs r.realmDefinitions)) () where toAnn Conjunctive = [] diff --git a/packages/coln-compiler/src/Coln/Core/Readback.hs b/packages/coln-compiler/src/Coln/Core/Readback.hs index 7fd5ce24..edece24f 100644 --- a/packages/coln-compiler/src/Coln/Core/Readback.hs +++ b/packages/coln-compiler/src/Coln/Core/Readback.hs @@ -21,13 +21,12 @@ instance Readback V.Head (S.El N) where readb n = \case V.LocalVar (FId i) -> S.LocalVar (BId (n - i - 1)) V.GlobalVar x v -> S.GlobalVar x v - V.Lookup x vs a -> S.Lookup x (readb n <$> vs) (readb n a) instance Readback V.Spine (S.El N -> S.El N) where readb n = \case V.Id -> \t -> t - V.App sp v -> \t -> S.App (readb n sp t) (readb n v) - V.Proj sp x -> \t -> S.Proj (readb n sp t) x + V.App fv sp v -> \t -> S.App fv (readb n sp t) (readb n v) + V.Proj l sp x -> \t -> S.Proj l (readb n sp t) x instance Readback V.BareNeutral (S.El N) where readb n ne = readb n ne.spine $ readb n ne.head @@ -49,10 +48,10 @@ instance (V.HasEvaluation c) => Readback (V.El c) (S.El c) where V.Neu ne -> readb n ne.spine $ readb n ne.head V.InitNeu ne -> readb n ne.spine $ readb n ne.name V.Code u a -> S.Code u (readb n a) - V.Lam dom body -> S.Lam (readb n dom) $ case V.scase @c of + V.Lam fv dom body -> S.Lam fv (readb n dom) $ case V.scase @c of SNominative -> readbClo n dom body SDescriptive -> readbClo n dom body - V.Cons d -> S.Cons $ case V.scase @c of + V.Cons l d -> S.Cons l $ case V.scase @c of SNominative -> readb n <$> d SDescriptive -> readb n <$> d V.Lit l -> S.Lit l @@ -100,7 +99,6 @@ instance (V.HasEvaluation c) => Readback (V.Ty c) (S.Ty c) where V.Record r -> S.Record $ readb n r V.Eq eq -> S.Eq $ readb n eq V.BuiltinTy b -> S.BuiltinTy b - V.EltOf x vs -> S.EltOf x (readb n <$> vs) instance Readback V.TypeBehavior S.TypeBehavior where readb n = \case diff --git a/packages/coln-compiler/src/Coln/Core/Syntax.hs b/packages/coln-compiler/src/Coln/Core/Syntax.hs index 82c717dc..30f6d3a2 100644 --- a/packages/coln-compiler/src/Coln/Core/Syntax.hs +++ b/packages/coln-compiler/src/Coln/Core/Syntax.hs @@ -19,14 +19,13 @@ data El :: Case -> Type where LocalVar :: BId -> El N GlobalVar :: Name -> V.El N -> El N Code :: Universe -> Ty c -> El c - Lam :: Ty N -> Abs El c -> El c - App :: El N -> El N -> El N - Cons :: Dict (El c) -> El c - Proj :: El N -> Name -> El N + Lam :: FunctionVariant -> Ty N -> Abs El c -> El c + App :: FunctionVariant -> El N -> El N -> El N + Cons :: Level -> Dict (El c) -> El c + Proj :: Level -> El N -> Name -> El N Init :: Ty N -> El D Lit :: Literal -> El N Is :: El N -> El D - Lookup :: TableName -> Dict (El N) -> Ty N -> El N data FunctionType ty = FunctionType { variant :: FunctionVariant @@ -53,7 +52,6 @@ data Ty :: Case -> Type where Eq :: EqualityType El Ty -> Ty N BuiltinTy :: BuiltinTy -> Ty N IsTy :: Ty N -> Ty D - EltOf :: TableName -> Dict (El N) -> Ty N data TypeBehavior = LikeU Universe diff --git a/packages/coln-compiler/src/Coln/Core/Value.hs b/packages/coln-compiler/src/Coln/Core/Value.hs index 1c110da3..31df1cf2 100644 --- a/packages/coln-compiler/src/Coln/Core/Value.hs +++ b/packages/coln-compiler/src/Coln/Core/Value.hs @@ -76,18 +76,17 @@ appClo (CloConst body) _ = body data Spine = Id - | App Spine (El N) - | Proj Spine Name + | App FunctionVariant Spine (El N) + | Proj Level Spine Name composeSpines :: Spine -> Spine -> Spine composeSpines s Id = s -composeSpines s (App s' v) = App (composeSpines s s') v -composeSpines s (Proj s' x) = Proj (composeSpines s s') x +composeSpines s (App fv s' v) = App fv (composeSpines s s') v +composeSpines s (Proj l s' x) = Proj l (composeSpines s s') x data Head = LocalVar FId | GlobalVar Name ~(El N) - | Lookup TableName (Dict (El N)) ~(Ty N) data Expansion = IntoCons (Dict (El N)) @@ -110,7 +109,7 @@ expandRecord recordType head spine desc = do let go :: Locals -> [(Name, Locals -> Ty N)] -> [El N] go _ [] = [] go vs ((x, ty) : rest) = do - let v = reflect head (Proj spine x) (ty vs) ((`proj` x) <$> desc) + let v = reflect head (Proj recordType.level spine x) (ty vs) ((`proj` x) <$> desc) v : go (LSnoc vs v) rest let tele = recordType.fieldTypes Dict @@ -134,9 +133,6 @@ reflect head spine ~ty edesc = do local :: FId -> Ty N -> El N local i a = reflect (LocalVar i) Id a Nothing -tableLookup :: TableName -> Dict (El N) -> Ty N -> El N -tableLookup x vs a = reflect (Lookup x vs a) Id a Nothing - data DecodedNeutral = DecodedNeutral { head :: Head , spine :: Spine @@ -174,18 +170,18 @@ data El :: Case -> Type where Neu :: Neutral -> El N InitNeu :: InitNeutral -> El N Code :: Universe -> Ty c -> El c - Lam :: ~(Ty N) -> Clo El c -> El c - Cons :: Dict (Evaluation El c) -> El c + Lam :: FunctionVariant -> ~(Ty N) -> Clo El c -> El c + Cons :: Level -> Dict (Evaluation El c) -> El c Lit :: Literal -> El N -app :: El c -> El N -> Evaluation El c -app (Lam _ clo) arg = appClo clo arg -app (Neu n) arg = - reflect n.head (App n.spine arg) (appTy n.ty arg) ((`app` arg) <$> n.description) -app _ _ = panic "ill-typed application" +app :: FunctionVariant -> El c -> El N -> Evaluation El c +app _ (Lam _ _ clo) arg = appClo clo arg +app fv (Neu n) arg = + reflect n.head (App fv n.spine arg) (appTy n.ty arg) ((flip (app fv) arg) <$> n.description) +app _ _ _ = panic "ill-typed application" coerceToFields :: El c -> Dict (Evaluation El c) -coerceToFields (Cons fields) = fields +coerceToFields (Cons _ fields) = fields coerceToFields (Neu n) = case n.expansion of IntoCons fields -> fields _ -> panic "unexpanded neutral of record type" @@ -235,7 +231,6 @@ data Ty :: Case -> Type where Record :: RecordType -> Ty D Eq :: EqualityType -> Ty N BuiltinTy :: BuiltinTy -> Ty N - EltOf :: TableName -> Dict (El N) -> Ty N instance DebugVal (Ty c) where debugVal = \case @@ -246,7 +241,6 @@ instance DebugVal (Ty c) where Record _ -> "Record" Eq _ -> "Eq" BuiltinTy _ -> "BuiltinTy" - EltOf _ _ -> "EltOf" instance LevelOf (Ty c) where levelOf = \case @@ -257,7 +251,6 @@ instance LevelOf (Ty c) where InitDecode _ -> Level Set HSet Eq ety -> Level (levelOf ety.at).mlevel (equalityHLevelOf (levelOf ety.at).hlevel) BuiltinTy _ -> Level Set HSet -- Only Int/String so far - EltOf _ _ -> Level Set HSet -- TODO behavior :: Ty c -> TypeBehavior behavior = \case @@ -270,7 +263,6 @@ behavior = \case Record rt -> LikeRecord rt Eq _ -> NoRules BuiltinTy bty -> LikeBuiltinTy bty - EltOf _ _ -> NoRules decode :: (HasEvaluation c) => El c -> Evaluation Ty c decode (Code _ a) = epure a diff --git a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs new file mode 100644 index 00000000..131d3b02 --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs @@ -0,0 +1,39 @@ +module Coln.MIR.Evaluation where + +import Coln.Common +import Coln.MIR.Params +import Coln.Core.Params + +import Coln.MIR.Syntax qualified as S +import Coln.MIR.Value qualified as V + +class Eval a b where + eval :: V.Locals -> a -> b + +evalAbs :: (Eval a b) => V.Locals -> S.Abs a -> V.Clo (V.El Set) b +evalAbs vs (S.Abs x body) = V.Clo x (\v -> eval (vs :> Pair SSet v) body) +evalAbs vs (S.AbsConst body) = V.CloConst (eval vs body) + +instance Eval (S.El l) (V.El l) where + eval vs = \case + S.LiftEl t -> V.LiftEl LSetTheory (eval vs t) + S.Var i -> levelCoerceFromMatch SSet (elemAt vs i) + S.Lookup tn args a -> + V.Neu $ V.Neutral (V.Lookup tn (eval vs <$> args) (eval vs a)) BwdNil + S.Code u a -> V.Code u (eval vs a) + S.Lam abs -> V.Lam SSetTheory (evalAbs vs abs) + S.Cons fields -> V.Cons (eval vs <$> fields) + S.Proj t x -> V.proj (eval vs t) x + S.Lit l -> V.Lit l + +instance Eval (S.Ty l) (V.Ty l) where + eval vs = \case + S.LiftTy t -> V.LiftTy LSetTheory (eval vs t) + S.U u -> V.U u + S.EltOf tn args -> V.EltOf tn (eval vs <$> args) + S.Function ft -> V.Function $ + V.FunctionType SSetTheory (eval vs ft.dom) (evalAbs vs ft.cod) + S.Record rt -> V.Record $ + V.RecordType vs $ flip eval <$> rt.fieldTypes + S.BuiltinTy t -> V.BuiltinTy t + S.Eq at lhs rhs -> V.Eq (eval vs at) (eval vs lhs) (eval vs rhs) diff --git a/packages/coln-compiler/src/Coln/MIR/Interpret.hs b/packages/coln-compiler/src/Coln/MIR/Interpret.hs index 194eca4f..15e4945d 100644 --- a/packages/coln-compiler/src/Coln/MIR/Interpret.hs +++ b/packages/coln-compiler/src/Coln/MIR/Interpret.hs @@ -3,72 +3,65 @@ module Coln.MIR.Interpret where -- Interpret Core syntax into MIR values import Coln.Common -import Coln.MIR.Value qualified as MV -import Coln.Core.Syntax qualified as CS -import Coln.Core.Globals +import Coln.MIR.Value qualified as V +import Coln.MIR.Params +import Coln.Core.Syntax qualified as S import Coln.Core.Params -import Coln.Core.Memoed (Memoed (..)) --- No FunctionalDependency here, because we interpret syntax into different --- parts! -class Interp a b where - interp :: Globals -> MV.Locals -> a -> b +class Interp a (f :: MLevel -> Type) | a -> f where + interp :: V.Globals -> V.Locals -> a -> Match SMLevel f --- We need to plumb through more information about variants in the syntax. --- --- Universe for Code --- FunctionVariant for Lam/App --- Level for Cons/Proj +interpAt :: (Interp a f, LevelCoerce f) => SMLevel l -> V.Globals -> V.Locals -> a -> f l +interpAt l0 g e t = case interp g e t of + Pair l1 v -> levelCoerce l1 l0 v --- This probably needs to also go through values. +-- Should this also be "compile"? --- Alternatives: --- - Coercion from TopLam and TheoryCode downward --- --- Arguably, the "right" way to do this is to plumb through that information. --- Or rather... looking at the SOGAT, this information is *not* part of the syntax --- for function/records, but *is* for universe operations. --- Which implies that we should plumb through for Code/Decode, but not for --- Lam/App/Cons/Proj... +instance Interp (S.El c) V.El where + interp g e = \case + S.LocalVar i -> elemAt e i + S.GlobalVar x _ -> elemAt g x + S.Code u a -> withUniverse u $ \su -> do + let (l0, l1) = (sDecodesInto su, sCodesInto su) + Pair l1 (V.Code su (interpAt l0 g e a)) + S.Lam fv _ abs -> withFunctionVariant fv.mlevel $ \sfv -> do + let (d, c) = (sDom sfv, sCod sfv) + let clo = case abs of + S.Abs x body -> V.Clo x (\v -> interpAt c g (e :> Pair d v) body) + S.AbsConst body -> V.CloConst (interpAt c g e body) + Pair c (V.Lam sfv clo) + S.App fv t0 t1 -> withFunctionVariant fv.mlevel $ \sfv -> do + let (d, c) = (sDom sfv, sCod sfv) + Pair c (V.app sfv (interpAt c g e t0) (interpAt d g e t1)) + S.Cons l fields -> withLevel l.mlevel $ \sl -> do + let fields' = interpAt sl g e <$> fields + Pair sl (V.Cons fields') + S.Proj l t0 x -> withLevel l.mlevel $ \sl -> do + let v = interpAt sl g e t0 + Pair sl (V.proj v x) + S.Init _ -> panic "cannot interpret init yet" + S.Lit l -> Pair SSet (V.Lit l) + S.Is t -> interp g e t --- I guess we are, in a sense, *always* in checking mode? --- Let's try coercion - --- Another option: bidirectional --- Another option: GADT - -interpAbs :: (Interp (f c) b) => Globals -> MV.Locals -> CS.Abs f c -> MV.Clo b -interpAbs g l (CS.Abs x body) = MV.Clo x (\v -> interp g (l :> v) body) -interpAbs g l (CS.AbsConst t) = MV.CloConst (interp g l t) - -appClo :: MV.Clo b -> MV.Model -> b -appClo (MV.Clo _ f) v = f v -appClo (MV.CloConst v) _ = v - -app :: MV.Top -> MV.Top -> MV.Top -app f v = case v of - MV.Model v -> case f of - MV.TopLam f -> appClo f v - MV.Model (MV.Lam f) -> MV.Model $ appClo f v - _ -> panic "expected lambda" - _ -> panic "cannot apply function to non-model value" - -instance Interp (CS.El c) MV.Top where - interp g l = \case - CS.LocalVar i -> MV.Model $ elemAt l i - CS.GlobalVar x _ -> do - let def = elemAt g.definitions x - interp g l def.body.stx - CS.Code u a -> case u of - (PropU; SetU) -> MV.Model $ MV.All $ interp g l a - TheoryU -> MV.TheoryCode $ interp g l a - CS.Lam _ abs -> MV.TopLam $ interpAbs g l abs - CS.App t0 t1 -> app (interp g l t0) (interp g l t1) - CS.Cons fields -> - - -instance Interp (CS.Ty c) MV.Ty where - interp = undefined - -instance Interp (CS.Ty c) MV.Theory where - interp = undefined +instance Interp (S.Ty c) V.Ty where + interp g e = \case + S.U u -> withUniverse u $ \su -> Pair (sCodesInto su) (V.U su) + S.Decode u t -> withUniverse u $ \su -> + Pair (sDecodesInto su) (V.decode su (interpAt (sCodesInto su) g e t)) + S.Function ft -> withFunctionVariant ft.variant.mlevel $ \sfv -> do + let (d, c) = (sDom sfv, sCod sfv) + let dom = interpAt d g e ft.dom + let cod = case ft.cod of + S.Abs x body -> V.Clo x (\v -> interpAt c g (e :> Pair d v) body) + S.AbsConst body -> V.CloConst (interpAt c g e body) + Pair c (V.Function (V.FunctionType sfv dom cod)) + S.Record rt -> withLevel rt.level.mlevel $ \sl -> do + let rt' = V.RecordType e (flip (interpAt sl g) <$> rt.fieldTypes) + Pair sl (V.Record rt') + S.Eq et -> do + let at = interpAt SSet g e et.at + let (lhs, rhs) = (interpAt SSet g e et.lhs, interpAt SSet g e et.rhs) + Pair SSet $ V.Eq at lhs rhs + S.BuiltinTy t -> do + Pair SSet $ V.BuiltinTy t + S.IsTy t -> interp g e t diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs new file mode 100644 index 00000000..64e9f6c8 --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -0,0 +1,120 @@ +-- SPDX-FileCopyrightText: 2026 Coln contributors +-- +-- SPDX-License-Identifier: Apache-2.0 OR MIT + +module Coln.MIR.Layout where + +import Data.Set qualified as Set +import Data.String (fromString) +import Data.Vector.Strict qualified as Vector + +import Coln.Common +-- import Coln.Core.Globals +import Coln.Core.Params +import Coln.MIR.Params +import Coln.MIR.Readback +import Coln.MIR.Syntax qualified as S +import Coln.MIR.Value qualified as V +import Coln.MIR.Memoed qualified as M +import Coln.MIR.Realm + +-- Layout is the process of creating a realm from a theory, along with the +-- universal model of that theory in the realm. + +freshenBy :: Name -> String -> Name +freshenBy (Name qual last) s = Name (qual ++ [last]) (fromString s) + +argName :: Set.Set Name -> V.Clo a b -> Name +argName _ (V.Clo x _) = x +argName used (V.CloConst _) = freshNameFor used + +data Scope = Scope + { len :: CtxLen + , names :: Bwd Name + , ctx :: Bwd (V.Ty Set) + , bound :: Bwd (V.El Set) + , locals :: V.Locals + , usedNames :: Set.Set Name + , realm :: RealmId + } + +emptyScope :: RealmId -> Scope +emptyScope = Scope 0 BwdNil BwdNil BwdNil BwdNil Set.empty + +bind :: Scope -> Name -> V.Ty Set -> (V.El Set, Scope) +bind sc x a = do + let v = V.local (FId sc.len) + sc' = Scope + { len = sc.len + 1 + , names = sc.names :> x + , ctx = sc.ctx :> a + , bound = sc.bound :> v + , locals = sc.locals :> (Pair SSet v) + , usedNames = Set.insert x sc.usedNames + , realm = sc.realm + } + (v, sc') + +args :: Scope -> [M.El Set] +args sc = [M.M (readb sc.len v) v | v <- toList sc.bound] + +layout :: Path -> Scope -> V.Ty Theory -> (Trie Generator, M.El Theory) +layout p sc = \case + V.LiftTy LSetTheory a -> do + let gt = Leaf (Fun sc.names sc.ctx a) + (gt, M.liftEl $ M.lookup (TableName sc.realm p) (args sc) (M.fromV sc.len a)) + V.U (inferSetCodes -> u) -> do + let gt = Leaf (Rel u sc.names sc.ctx) + (gt, M.code u $ M.eltOf (TableName sc.realm p) (args sc)) + V.Function ft -> case ft.variant of + SSetTheory -> do + let x = argName sc.usedNames ft.cod + let (v, sc') = bind sc x ft.dom + let (gt, m) = layout p sc' (V.appClo ft.cod v) + (gt, M.lam sc.locals (S.Abs x m.stx)) + V.Record rt -> do + let go _ [] = ([], []) + go l ((x, a) : rest) = do + let (gt, m) = layout (p :> x) sc (a l) + let (gts, ms) = go (l :> Pair STheory m.val) rest + (gt : gts, m : ms) + let (gts, ms) = go rt.capture (toList rt.fieldTypes) + let gt = Node $ Dict rt.fieldTypes.head (Vector.fromList gts) + (gt, M.cons (Dict rt.fieldTypes.head (Vector.fromList ms))) + +layoutTop :: RealmId -> V.Ty Theory -> (Trie Generator, M.El Theory) +layoutTop x = layout BwdNil (emptyScope x) + +-- Walk through the term, and replace any conjunctive queries with lookups of +-- emitted views, which will be incrementally maintained +-- cache :: Path -> Scope -> V.El N -> (Trie Generator, M.El N) +-- cache p sc v = case v of +-- V.Code a -> do +-- let gt = Leaf (View (toList sc.names) (toList sc.ctx) (readb sc.len a)) +-- let a' = V.EltOf (TableName sc.realm p) (fromList $ zip (toList (sc.names)) (toList sc.bound)) +-- (gt, M.code (M.fromVTy sc.len a')) +-- V.Lam a f -> do +-- let x = argName sc.usedNames f +-- let (v, sc') = bind sc x a +-- let (gt, m) = cache p sc' (V.appClo f v) +-- let m' = M.lam sc.locals (M.fromVTy sc.len a) (S.Abs x m) +-- (gt, m') +-- V.Cons fields -> do +-- let go [] = ([], []) +-- go ((x, v) : rest) = do +-- let (gt, m) = cache (p :> x) sc v +-- let (gts, ms) = go rest +-- (gt : gts, m : ms) +-- let (gts, ms) = go (toList fields) +-- let m = M.cons (Dict fields.head (Vector.fromList ms)) +-- (Node $ Dict fields.head (Vector.fromList gts), m) +-- (V.Neu _; V.InitNeu _; V.Lit _) -> (Node (fromList []), M.fromVEl sc.len v) + +-- -- `cache` should produce an element whose behavior with respect to type-checking +-- -- is precisely the same as before. + +-- -- In other words, `cache` should only serve to *annotate* each query with extra +-- -- information about how to look it up. + +-- -- layoutDecls :: OMap Name (Definition Local) -> ([(Name, Trie Generator)], OMap Name (Definition Local)) +-- -- layoutDecls ds diff --git a/packages/coln-compiler/src/Coln/MIR/Memoed.hs b/packages/coln-compiler/src/Coln/MIR/Memoed.hs new file mode 100644 index 00000000..d13b614f --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Memoed.hs @@ -0,0 +1,43 @@ +module Coln.MIR.Memoed where + +import Coln.Common +import Coln.Core.Params +import Coln.MIR.Params +import Coln.MIR.Syntax qualified as S +import Coln.MIR.Value qualified as V +import Coln.MIR.Readback +import Coln.MIR.Evaluation + +data Memoed (s :: MLevel -> Type) (v :: MLevel -> Type) (l :: MLevel) = M + { stx :: s l + , val :: ~(v l) + } + +type El = Memoed S.El V.El +type Ty = Memoed S.Ty V.Ty + +var :: V.Locals -> BId -> El Set +var vs i = M (S.Var i) (levelCoerceFromMatch SSet (elemAt vs i)) + +fromV :: (Readback (a l) (b l)) => CtxLen -> a l -> Memoed b a l +fromV n v = M (readb n v) v + +liftEl :: El Set -> El Theory +liftEl (M s v) = M (S.LiftEl s) (V.LiftEl LSetTheory v) + +lookup :: TableName -> [El Set] -> Ty Set -> El Set +lookup tn args a = M (S.Lookup tn ((.stx) <$> args) a.stx) (V.lookup tn ((.val) <$> args) a.val) + +code :: SUniverse Set Theory -> Ty Set -> El Theory +code u (M s v) = M (S.Code u s) (V.Code u v) + +eltOf :: TableName -> [El Set] -> Ty Set +eltOf tn args = M (S.EltOf tn ((.stx) <$> args)) (V.EltOf tn ((.val) <$> args)) + +lam :: V.Locals -> S.Abs (S.El Theory) -> El Theory +lam vs abs = do + let clo = evalAbs vs abs + M (S.Lam abs) (V.Lam SSetTheory clo) + +cons :: Dict (El l) -> El l +cons fields = M (S.Cons ((.stx) <$> fields)) (V.Cons ((.val) <$> fields)) diff --git a/packages/coln-compiler/src/Coln/MIR/Params.hs b/packages/coln-compiler/src/Coln/MIR/Params.hs new file mode 100644 index 00000000..bd2dde45 --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Params.hs @@ -0,0 +1,72 @@ +module Coln.MIR.Params where + +import Coln.Common +import Coln.Core.Params + +data SMLevel :: MLevel -> Type where + SSet :: SMLevel Set + STheory :: SMLevel Theory + STop :: SMLevel Top + +withLevel :: MLevel -> (forall l. SMLevel l -> a) -> a +withLevel l f = case l of + Set -> f SSet + Theory -> f STheory + Top -> f STop + +class LevelCoerce (f :: MLevel -> Type) where + levelCoerce :: SMLevel l0 -> SMLevel l1 -> f l0 -> f l1 + +levelCoerceFromMatch :: (LevelCoerce f) => SMLevel l -> Match SMLevel f -> f l +levelCoerceFromMatch l1 (Pair l0 v) = levelCoerce l0 l1 v + +data Lift :: MLevel -> MLevel -> Type where + LSetTheory :: Lift Set Theory + LTheoryTop :: Lift Theory Top + +data SUniverse :: MLevel -> MLevel -> Type where + SSetU :: SUniverse Set Theory + SPropU :: SUniverse Set Theory + STheoryU :: SUniverse Theory Top + +sDecodesInto :: SUniverse l0 l1 -> SMLevel l0 +sDecodesInto = \case + SSetU -> SSet + SPropU -> SSet + STheoryU -> STheory + +sCodesInto :: SUniverse l0 l1 -> SMLevel l1 +sCodesInto = \case + SSetU -> STheory + SPropU -> STheory + STheoryU -> STop + +withUniverse :: Universe -> (forall l0 l1. SUniverse l0 l1 -> a) -> a +withUniverse u f = case u of + SetU -> f SSetU + PropU -> f SPropU + TheoryU -> f STheoryU + +inferSetCodes :: SUniverse l Theory -> SUniverse Set Theory +inferSetCodes SSetU = SSetU +inferSetCodes SPropU = SPropU + +data SFunctionVariant :: MLevel -> MLevel -> Type where + SSetTheory :: SFunctionVariant Set Theory + STheoryTop :: SFunctionVariant Theory Top + +sDom :: SFunctionVariant l0 l1 -> SMLevel l0 +sDom = \case + SSetTheory -> SSet + STheoryTop -> STheory + +sCod :: SFunctionVariant l0 l1 -> SMLevel l1 +sCod = \case + SSetTheory -> STheory + STheoryTop -> STop + +withFunctionVariant :: FunctionVariantMLevel -> (forall l0 l1. SFunctionVariant l0 l1 -> a) -> a +withFunctionVariant fv f = case fv of + SetTheory -> f SSetTheory + TheoryTop -> f STheoryTop + diff --git a/packages/coln-compiler/src/Coln/MIR/Readback.hs b/packages/coln-compiler/src/Coln/MIR/Readback.hs new file mode 100644 index 00000000..cfba4d50 --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Readback.hs @@ -0,0 +1,60 @@ +module Coln.MIR.Readback where + +import Coln.Common +import Coln.Core.Params +import Coln.MIR.Params +import Coln.MIR.Value qualified as V +import Coln.MIR.Syntax qualified as S + +type CtxLen = Int + +class Readback a b | a -> b where + readb :: CtxLen -> a -> b + +instance Readback V.Head (S.El Set) where + readb n = \case + V.Var (FId i) -> S.Var (BId (n - i - 1)) + V.Lookup x args a -> S.Lookup x (readb n <$> args) (readb n a) + +instance Readback (V.El Set) (S.El Set) where + readb n = \case + V.Neu ne -> do + let go t BwdNil = t + go t (xs :> x) = S.Proj (go t xs) x + go (readb n ne.head) ne.spine + V.Cons fields -> S.Cons $ readb n <$> fields + V.Lit l -> S.Lit l + +fresh :: CtxLen -> V.El Set +fresh n = V.local (FId n) + +instance Readback (V.Ty Set) (S.Ty Set) where + readb n = \case + V.EltOf tn args -> S.EltOf tn (readb n <$> args) + V.BuiltinTy t -> S.BuiltinTy t + V.Eq at lhs rhs -> S.Eq (readb n at) (readb n lhs) (readb n rhs) + V.Record rt -> do + let go _ _ [] = [] + go n' vs ((x, k):rest) = + (x, readb n' (k vs)):(go (n' + 1) (vs :> Pair SSet (fresh n')) rest) + let fieldTypes = fromList $ go n rt.capture (toList rt.fieldTypes) + S.Record $ S.RecordType fieldTypes + +instance Readback (V.Ty Theory) (S.Ty Theory) where + readb n = \case + V.LiftTy LSetTheory a -> S.LiftTy (readb n a) + V.U SPropU -> S.U SPropU + V.U SSetU -> S.U SSetU + V.Function ft -> undefined + +readbClo :: (Readback a b) => CtxLen -> V.Clo (V.El Set) a -> S.Abs b +readbClo n (V.Clo x f) = S.Abs x (readb (n + 1) (f (fresh n))) +readbClo n (V.CloConst t) = S.AbsConst (readb n t) + +instance Readback (V.El Theory) (S.El Theory) where + readb n = \case + V.LiftEl LSetTheory v -> S.LiftEl (readb n v) + V.Code SPropU a -> S.Code SPropU (readb n a) + V.Code SSetU a -> S.Code SSetU (readb n a) + V.Lam SSetTheory clo -> S.Lam (readbClo n clo) + V.Cons fields -> S.Cons $ readb n <$> fields diff --git a/packages/coln-compiler/src/Coln/MIR/Realm.hs b/packages/coln-compiler/src/Coln/MIR/Realm.hs new file mode 100644 index 00000000..258e09af --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Realm.hs @@ -0,0 +1,23 @@ +module Coln.MIR.Realm where + +import Coln.Common +import Coln.Core.Params +import Coln.MIR.Params +import Coln.MIR.Value qualified as V +import Coln.MIR.Memoed qualified as M + +data Generator + = Rel (SUniverse Set Theory) (Bwd Name) (Bwd (V.Ty Set)) + | Fun (Bwd Name) (Bwd (V.Ty Set)) (V.Ty Set) + +data RealmDefinition = RealmDefinition + { body :: M.El Theory + , ty :: V.Ty Theory + } + +data Realm = Realm + { root :: V.El Theory + , rootType :: V.Ty Theory + , generators :: Trie Generator + , realmDefinitions :: OMap Name RealmDefinition + } diff --git a/packages/coln-compiler/src/Coln/MIR/Syntax.hs b/packages/coln-compiler/src/Coln/MIR/Syntax.hs index 2df00de6..fea261a3 100644 --- a/packages/coln-compiler/src/Coln/MIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/MIR/Syntax.hs @@ -1 +1,36 @@ module Coln.MIR.Syntax where + +import Coln.Common +import Coln.MIR.Params +import Coln.Core.Params + +data Abs a = Abs Name a | AbsConst a + +data El :: MLevel -> Type where + LiftEl :: El Set -> El Theory + Var :: BId -> El Set + Lookup :: TableName -> [El Set] -> Ty Set -> El Set + Code :: SUniverse Set Theory -> Ty Set -> El Theory + Lam :: Abs (El Theory) -> El Theory + Cons :: Dict (El l) -> El l + Proj :: El l -> Name -> El l + Lit :: Literal -> El Set + + +data FunctionType = FunctionType + { dom :: Ty Set + , cod :: Abs (Ty Theory) + } + +data RecordType l = RecordType + { fieldTypes :: Dict (Ty l) } + +data Ty :: MLevel -> Type where + LiftTy :: Ty Set -> Ty Theory + U :: SUniverse Set Theory -> Ty Theory + EltOf :: TableName -> [El Set] -> Ty Set + Function :: FunctionType -> Ty Theory + Record :: RecordType l -> Ty l + BuiltinTy :: BuiltinTy -> Ty Set + Eq :: Ty Set -> El Set -> El Set -> Ty Set + diff --git a/packages/coln-compiler/src/Coln/MIR/Value.hs b/packages/coln-compiler/src/Coln/MIR/Value.hs index b070d489..259ed394 100644 --- a/packages/coln-compiler/src/Coln/MIR/Value.hs +++ b/packages/coln-compiler/src/Coln/MIR/Value.hs @@ -1,65 +1,105 @@ module Coln.MIR.Value where --- MIR consists of models in a context which only has set-level variables - import Coln.Common import Coln.Core.Params +import Coln.MIR.Params -type Locals = Bwd Model - -data Clo a - = Clo Name (Model -> a) - | CloConst a +-- MIR consists of models in a context which only has set-level variables -data Shape - = RowId TableName - | Tuple (Dict Shape) - | BuiltinTy BuiltinTy +data Head + = Var FId + | Lookup TableName [El Set] (Ty Set) data Neutral = Neutral - { head :: FId - , spine :: Bwd Name -- only projections + { head :: Head + , spine :: Bwd Name } -data El - = Neu Neutral - | SetCons (Dict El) - | Lit Literal - | Single Ty +type Locals = Bwd (Match SMLevel El) -data Pred - = EltOf TableName (Maybe El) [Maybe El] - | And (Dict Pred) +type Globals = OMap Name (Match SMLevel El) -data Ty = Ty - { shape :: Shape - , pred :: El -> Pred - } +data Clo a b = Clo Name (a -> b) | CloConst b + +appClo :: Clo a b -> a -> b +appClo (Clo _ f) v = f v +appClo (CloConst v) _ = v + +data El :: MLevel -> Type where + LiftEl :: Lift l0 l1 -> El l0 -> El l1 + Neu :: Neutral -> El Set + Code :: SUniverse l0 l1 -> Ty l0 -> El l1 + Lam :: SFunctionVariant l0 l1 -> Clo (El l0) (El l1) -> El l1 + Cons :: Dict (El l) -> El l + Lit :: Literal -> El Set + +local :: FId -> El Set +local i = Neu $ Neutral (Var i) BwdNil + +lookup :: TableName -> [El Set] -> Ty Set -> El Set +lookup tn args a = Neu $ Neutral (Lookup tn args a) BwdNil + +app :: SFunctionVariant l0 l1 -> El l1 -> El l0 -> El l1 +app fv (Lam fv' clo) v = case (fv, fv') of + (SSetTheory, SSetTheory) -> appClo clo v + (STheoryTop, STheoryTop) -> appClo clo v +app _ _ _ = panic "can only apply lambda" + +proj :: El l -> Name -> El l +proj (Neu n) x = Neu $ n { spine = n.spine :> x } +proj (Cons fields) x = elemAt fields x +proj _ _ = panic "can only project from neutral or cons" + +decode :: SUniverse l0 l1 -> El l1 -> Ty l0 +decode su (Code su' a) = case (su, su') of + (SPropU, SPropU) -> a + (SSetU, SPropU) -> a + (SSetU, SSetU) -> a + (SPropU, SSetU) -> panic "tried to decode a set into a proposition" + (STheoryU, STheoryU) -> a +decode _ _ = panic "tried to decode a non-code" + +instance LevelCoerce El where + levelCoerce SSet SSet v = v + levelCoerce STheory STheory v = v + levelCoerce STop STop v = v + levelCoerce SSet STheory v = LiftEl LSetTheory v + levelCoerce STheory STop v = LiftEl LTheoryTop v + levelCoerce SSet STop v = LiftEl LTheoryTop (LiftEl LSetTheory v) + levelCoerce STheory SSet (LiftEl LSetTheory v) = v + levelCoerce STop STheory (LiftEl LTheoryTop v) = v + levelCoerce STop SSet (LiftEl LTheoryTop (LiftEl LSetTheory v)) = v + levelCoerce _ _ _ = panic "cannot level coerce" -data Model - = All Ty - | Lift El - | Lam (Clo Model) - | ModelCons (Dict Model) -data FunctionType = FunctionType - { dom :: Ty - , cod :: El -> Theory +data FunctionType (l0 :: MLevel) (l1 :: MLevel) = FunctionType + { variant :: SFunctionVariant l0 l1 + , dom :: Ty l0 + , cod :: Clo (El l0) (Ty l1) } -data RecordType = RecordType +data RecordType (l :: MLevel) = RecordType { capture :: Locals - , fieldTypes :: Dict (Locals -> Theory) + , fieldTypes :: Dict (Locals -> Ty l) } -data Theory - = SetU - | PropU - | Elt Ty - | Function FunctionType - | Record RecordType - -data Top - = Model Model - | TheoryCode Theory - | TopLam (Clo Top) +data Ty :: MLevel -> Type where + LiftTy :: Lift l0 l1 -> Ty l0 -> Ty l1 + U :: SUniverse l0 l1 -> Ty l1 + EltOf :: TableName -> [El Set] -> Ty Set + Function :: FunctionType l0 l1 -> Ty l1 + Record :: RecordType l -> Ty l + BuiltinTy :: BuiltinTy -> Ty Set + Eq :: Ty Set -> El Set -> El Set -> Ty Set + +instance LevelCoerce Ty where + levelCoerce SSet SSet v = v + levelCoerce STheory STheory v = v + levelCoerce STop STop v = v + levelCoerce SSet STheory v = LiftTy LSetTheory v + levelCoerce STheory STop v = LiftTy LTheoryTop v + levelCoerce SSet STop v = LiftTy LTheoryTop (LiftTy LSetTheory v) + levelCoerce STheory SSet (LiftTy LSetTheory v) = v + levelCoerce STop STheory (LiftTy LTheoryTop v) = v + levelCoerce STop SSet (LiftTy LTheoryTop (LiftTy LSetTheory v)) = v + levelCoerce _ _ _ = panic "cannot lift" diff --git a/packages/coln-compiler/src/Coln/SIR/Realm.hs b/packages/coln-compiler/src/Coln/SIR/Realm.hs new file mode 100644 index 00000000..e95b7937 --- /dev/null +++ b/packages/coln-compiler/src/Coln/SIR/Realm.hs @@ -0,0 +1,34 @@ +module Coln.SIR.Realm where + +import Coln.Common +import Coln.Core.Params +import Coln.SIR.Syntax + +data EntityType + = Table + | View + +data Entity = Entity + { entityType :: EntityType + , columnNames :: [Name] + , columnShapes :: [Shape] + , primaryKey :: Maybe [Int] + } + +data Definition = Definition + { inCtx :: [Query] + , definand :: TableName + , args :: [El Set] + } + +data Law = Law + { inCtx :: [Query] + , antecedent :: Pred + , consequent :: Pred + } + +data Realm = Realm + { entities :: Trie Entity + , definitions :: Trie Definition + , laws :: Trie Law + } diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs new file mode 100644 index 00000000..e671c91b --- /dev/null +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -0,0 +1,85 @@ +module Coln.SIR.Separate where + +import Coln.Common +import Coln.Core.Params +import Coln.MIR.Params +import Coln.MIR.Value qualified as V +import Coln.SIR.Syntax qualified as S + +type CtxLen = Int + +class Separate a b | a -> b where + separate :: CtxLen -> a -> b + +instance Separate V.Head (S.El Set) where + separate n = \case + V.Var (FId i) -> S.Var (BId (n - i - 1)) + V.Lookup tn args ret -> do + let args' = separate n <$> args + let pred = S.Atom tn Nothing (args' ++ [S.Var 0]) + S.Single $ S.Query (shapeOf ret) (S.Abs Nothing pred) + +instance Separate (V.El Set) (S.El Set) where + separate n = \case + V.Neu ne -> do + let go t BwdNil = t + go t (xs :> x) = S.Proj (go t xs) x + go (separate n ne.head) ne.spine + V.Cons fields -> S.Cons $ separate n <$> fields + V.Lit l -> S.Lit l + +separateClo :: (Separate a b) => CtxLen -> V.Clo (V.El Set) a -> S.Abs b +separateClo n (V.Clo x body) = S.Abs (Just x) (separate (n + 1) (body (V.local (FId n)))) +separateClo n (V.CloConst body) = S.AbsConst (separate n body) + +instance Separate (V.El Theory) (S.El Theory) where + separate n = \case + V.LiftEl LSetTheory v -> S.LiftEl (separate n v) + V.Code SSetU a -> S.Multi (separate n a) + V.Code SPropU a -> S.Holds (asPred n a) + V.Lam SSetTheory clo -> S.Lam (separateClo n clo) + V.Cons fields -> S.Cons $ separate n <$> fields + +shapeOf :: V.Ty Set -> S.Shape +shapeOf = \case + V.EltOf x _ -> S.RowId x + V.Record rt -> do + let go [] _ _ = [] + go ((x, k):rest) vs v = do + let v' = V.proj v x + (x, shapeOf (k vs)) : (go rest (vs :> Pair SSet v') v) + let v = V.local (FId 0) + S.Tuple $ fromList $ go (toList rt.fieldTypes) rt.capture v + V.BuiltinTy t -> S.BuiltinTy t + V.Eq _ _ _ -> S.unitShape + +predAt :: CtxLen -> V.Ty Set -> V.El Set -> S.Pred +predAt n = \case + V.EltOf x args -> \v -> + S.Atom x (Just (separate n v)) (separate n <$> args) + V.Record rt -> \v -> do + let go [] _ = [] + go ((x, k):rest) vs = do + let v' = V.proj v x + (x, predAt n (k vs) v') : (go rest (vs :> Pair SSet v')) + S.And $ fromList $ go (toList rt.fieldTypes) rt.capture + V.BuiltinTy _ -> \_ -> S.truePred + V.Eq at lhs rhs -> \_ -> + S.Eq (shapeOf at) (separate n lhs) (separate n rhs) + +asPred :: CtxLen -> V.Ty Set -> S.Pred +asPred n = \case + V.EltOf x args -> S.Atom x Nothing (separate n <$> args) + V.Record rt -> do + let v = V.local (FId n) + let go [] _ = [] + go ((x, k):rest) vs = do + let v' = V.proj v x + (x, asPred n (k vs)) : (go rest (vs :> Pair SSet v')) + S.And $ fromList $ go (toList rt.fieldTypes) rt.capture + V.BuiltinTy _ -> S.truePred + V.Eq at lhs rhs -> S.Eq (shapeOf at) (separate n lhs) (separate n rhs) + +instance Separate (V.Ty Set) S.Query where + separate n a = + S.Query (shapeOf a) (S.Abs Nothing (predAt (n + 1) a (V.local (FId n)))) diff --git a/packages/coln-compiler/src/Coln/SIR/Syntax.hs b/packages/coln-compiler/src/Coln/SIR/Syntax.hs new file mode 100644 index 00000000..99332be5 --- /dev/null +++ b/packages/coln-compiler/src/Coln/SIR/Syntax.hs @@ -0,0 +1,41 @@ +module Coln.SIR.Syntax where + +import Coln.Common +import Coln.Core.Params + +data El :: MLevel -> Type where + LiftEl :: El Set -> El Theory + Var :: BId -> El Set + Single :: Query -> El Set + Proj :: El Set -> Name -> El Set + Holds :: Pred -> El Theory + Multi :: Query -> El Theory + Lam :: Abs (El Theory) -> El Theory + Cons :: Dict (El l) -> El l + Lit :: Literal -> El Set + +data Pred + = Atom TableName (Maybe (El Set)) [El Set] + | And (Dict Pred) + | Eq Shape (El Set) (El Set) + +data Shape + = RowId TableName + | Tuple (Dict Shape) + | BuiltinTy BuiltinTy + +unitShape :: Shape +unitShape = Tuple (fromList []) + +truePred :: Pred +truePred = And (fromList []) + +data Abs a + = Abs (Maybe Name) a + | AbsConst a + +data Query = Query + { shape :: Shape + , pred :: Abs Pred + } + From 9be8ed429ce57fae23142239058efdeddb6d3911 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Thu, 20 Aug 2026 11:17:23 +0100 Subject: [PATCH 03/42] output views by caching definitions --- packages/coln-compiler/src/Coln/Common.hs | 3 + .../coln-compiler/src/Coln/MIR/Evaluation.hs | 2 +- .../coln-compiler/src/Coln/MIR/Interpret.hs | 4 +- packages/coln-compiler/src/Coln/MIR/Layout.hs | 34 --------- packages/coln-compiler/src/Coln/MIR/Memoed.hs | 6 +- .../coln-compiler/src/Coln/MIR/Readback.hs | 2 +- packages/coln-compiler/src/Coln/MIR/Syntax.hs | 2 +- packages/coln-compiler/src/Coln/MIR/Value.hs | 4 +- packages/coln-compiler/src/Coln/SIR/Cache.hs | 72 +++++++++++++++++++ packages/coln-compiler/src/Coln/SIR/Realm.hs | 4 +- .../coln-compiler/src/Coln/SIR/Separate.hs | 29 +++----- packages/coln-compiler/src/Coln/SIR/Syntax.hs | 16 ++--- 12 files changed, 103 insertions(+), 75 deletions(-) create mode 100644 packages/coln-compiler/src/Coln/SIR/Cache.hs diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index fcde9a48..066b84a5 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -111,6 +111,9 @@ class ToList a e | a -> e where class FromList a e | a -> e where fromList :: [e] -> a +instance FromList (Vector a) a where + fromList = V.fromList + -- Partial orderings -------------------------------------------------------------------------------- diff --git a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs index 131d3b02..8f9e82e2 100644 --- a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs +++ b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs @@ -21,7 +21,7 @@ instance Eval (S.El l) (V.El l) where S.Lookup tn args a -> V.Neu $ V.Neutral (V.Lookup tn (eval vs <$> args) (eval vs a)) BwdNil S.Code u a -> V.Code u (eval vs a) - S.Lam abs -> V.Lam SSetTheory (evalAbs vs abs) + S.Lam dom abs -> V.Lam SSetTheory (eval vs dom) (evalAbs vs abs) S.Cons fields -> V.Cons (eval vs <$> fields) S.Proj t x -> V.proj (eval vs t) x S.Lit l -> V.Lit l diff --git a/packages/coln-compiler/src/Coln/MIR/Interpret.hs b/packages/coln-compiler/src/Coln/MIR/Interpret.hs index 15e4945d..94a7e785 100644 --- a/packages/coln-compiler/src/Coln/MIR/Interpret.hs +++ b/packages/coln-compiler/src/Coln/MIR/Interpret.hs @@ -24,12 +24,12 @@ instance Interp (S.El c) V.El where S.Code u a -> withUniverse u $ \su -> do let (l0, l1) = (sDecodesInto su, sCodesInto su) Pair l1 (V.Code su (interpAt l0 g e a)) - S.Lam fv _ abs -> withFunctionVariant fv.mlevel $ \sfv -> do + S.Lam fv dom abs -> withFunctionVariant fv.mlevel $ \sfv -> do let (d, c) = (sDom sfv, sCod sfv) let clo = case abs of S.Abs x body -> V.Clo x (\v -> interpAt c g (e :> Pair d v) body) S.AbsConst body -> V.CloConst (interpAt c g e body) - Pair c (V.Lam sfv clo) + Pair c (V.Lam sfv (interpAt d g e dom) clo) S.App fv t0 t1 -> withFunctionVariant fv.mlevel $ \sfv -> do let (d, c) = (sDom sfv, sCod sfv) Pair c (V.app sfv (interpAt c g e t0) (interpAt d g e t1)) diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs index 64e9f6c8..3206930b 100644 --- a/packages/coln-compiler/src/Coln/MIR/Layout.hs +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -84,37 +84,3 @@ layout p sc = \case layoutTop :: RealmId -> V.Ty Theory -> (Trie Generator, M.El Theory) layoutTop x = layout BwdNil (emptyScope x) - --- Walk through the term, and replace any conjunctive queries with lookups of --- emitted views, which will be incrementally maintained --- cache :: Path -> Scope -> V.El N -> (Trie Generator, M.El N) --- cache p sc v = case v of --- V.Code a -> do --- let gt = Leaf (View (toList sc.names) (toList sc.ctx) (readb sc.len a)) --- let a' = V.EltOf (TableName sc.realm p) (fromList $ zip (toList (sc.names)) (toList sc.bound)) --- (gt, M.code (M.fromVTy sc.len a')) --- V.Lam a f -> do --- let x = argName sc.usedNames f --- let (v, sc') = bind sc x a --- let (gt, m) = cache p sc' (V.appClo f v) --- let m' = M.lam sc.locals (M.fromVTy sc.len a) (S.Abs x m) --- (gt, m') --- V.Cons fields -> do --- let go [] = ([], []) --- go ((x, v) : rest) = do --- let (gt, m) = cache (p :> x) sc v --- let (gts, ms) = go rest --- (gt : gts, m : ms) --- let (gts, ms) = go (toList fields) --- let m = M.cons (Dict fields.head (Vector.fromList ms)) --- (Node $ Dict fields.head (Vector.fromList gts), m) --- (V.Neu _; V.InitNeu _; V.Lit _) -> (Node (fromList []), M.fromVEl sc.len v) - --- -- `cache` should produce an element whose behavior with respect to type-checking --- -- is precisely the same as before. - --- -- In other words, `cache` should only serve to *annotate* each query with extra --- -- information about how to look it up. - --- -- layoutDecls :: OMap Name (Definition Local) -> ([(Name, Trie Generator)], OMap Name (Definition Local)) --- -- layoutDecls ds diff --git a/packages/coln-compiler/src/Coln/MIR/Memoed.hs b/packages/coln-compiler/src/Coln/MIR/Memoed.hs index d13b614f..9e104bdf 100644 --- a/packages/coln-compiler/src/Coln/MIR/Memoed.hs +++ b/packages/coln-compiler/src/Coln/MIR/Memoed.hs @@ -34,10 +34,10 @@ code u (M s v) = M (S.Code u s) (V.Code u v) eltOf :: TableName -> [El Set] -> Ty Set eltOf tn args = M (S.EltOf tn ((.stx) <$> args)) (V.EltOf tn ((.val) <$> args)) -lam :: V.Locals -> S.Abs (S.El Theory) -> El Theory -lam vs abs = do +lam :: V.Locals -> Ty Set -> S.Abs (S.El Theory) -> El Theory +lam vs dom abs = do let clo = evalAbs vs abs - M (S.Lam abs) (V.Lam SSetTheory clo) + M (S.Lam dom.stx abs) (V.Lam SSetTheory dom.val clo) cons :: Dict (El l) -> El l cons fields = M (S.Cons ((.stx) <$> fields)) (V.Cons ((.val) <$> fields)) diff --git a/packages/coln-compiler/src/Coln/MIR/Readback.hs b/packages/coln-compiler/src/Coln/MIR/Readback.hs index cfba4d50..335275c9 100644 --- a/packages/coln-compiler/src/Coln/MIR/Readback.hs +++ b/packages/coln-compiler/src/Coln/MIR/Readback.hs @@ -56,5 +56,5 @@ instance Readback (V.El Theory) (S.El Theory) where V.LiftEl LSetTheory v -> S.LiftEl (readb n v) V.Code SPropU a -> S.Code SPropU (readb n a) V.Code SSetU a -> S.Code SSetU (readb n a) - V.Lam SSetTheory clo -> S.Lam (readbClo n clo) + V.Lam SSetTheory dom clo -> S.Lam (readb n dom) (readbClo n clo) V.Cons fields -> S.Cons $ readb n <$> fields diff --git a/packages/coln-compiler/src/Coln/MIR/Syntax.hs b/packages/coln-compiler/src/Coln/MIR/Syntax.hs index fea261a3..f595137d 100644 --- a/packages/coln-compiler/src/Coln/MIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/MIR/Syntax.hs @@ -11,7 +11,7 @@ data El :: MLevel -> Type where Var :: BId -> El Set Lookup :: TableName -> [El Set] -> Ty Set -> El Set Code :: SUniverse Set Theory -> Ty Set -> El Theory - Lam :: Abs (El Theory) -> El Theory + Lam :: Ty Set -> Abs (El Theory) -> El Theory Cons :: Dict (El l) -> El l Proj :: El l -> Name -> El l Lit :: Literal -> El Set diff --git a/packages/coln-compiler/src/Coln/MIR/Value.hs b/packages/coln-compiler/src/Coln/MIR/Value.hs index 259ed394..e2e01dc9 100644 --- a/packages/coln-compiler/src/Coln/MIR/Value.hs +++ b/packages/coln-compiler/src/Coln/MIR/Value.hs @@ -29,7 +29,7 @@ data El :: MLevel -> Type where LiftEl :: Lift l0 l1 -> El l0 -> El l1 Neu :: Neutral -> El Set Code :: SUniverse l0 l1 -> Ty l0 -> El l1 - Lam :: SFunctionVariant l0 l1 -> Clo (El l0) (El l1) -> El l1 + Lam :: SFunctionVariant l0 l1 -> Ty l0 -> Clo (El l0) (El l1) -> El l1 Cons :: Dict (El l) -> El l Lit :: Literal -> El Set @@ -40,7 +40,7 @@ lookup :: TableName -> [El Set] -> Ty Set -> El Set lookup tn args a = Neu $ Neutral (Lookup tn args a) BwdNil app :: SFunctionVariant l0 l1 -> El l1 -> El l0 -> El l1 -app fv (Lam fv' clo) v = case (fv, fv') of +app fv (Lam fv' _ clo) v = case (fv, fv') of (SSetTheory, SSetTheory) -> appClo clo v (STheoryTop, STheoryTop) -> appClo clo v app _ _ _ = panic "can only apply lambda" diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs new file mode 100644 index 00000000..03ff8682 --- /dev/null +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -0,0 +1,72 @@ +module Coln.SIR.Cache where + +import Coln.Common +import Coln.Core.Params +import Coln.MIR.Params +import Coln.MIR.Value qualified as V +import Coln.SIR.Realm +import Coln.SIR.Syntax qualified as S +import Coln.SIR.Separate + +import Data.Set qualified as Set + +data Scope = Scope + { len :: Int + , ctx :: Bwd S.Query + , names :: Bwd Name + , bound :: Bwd (V.El Set) + , used :: Set.Set Name + , realm :: RealmId + } + +bind :: Scope -> Maybe Name -> V.Ty Set -> (Name, V.El Set, Scope) +bind sc mx a = do + let q = separate sc.len a + let x = case mx of + Just x -> x + Nothing -> freshNameFor sc.used + let v = V.local (FId sc.len) + let sc' = sc + { len = sc.len + 1 + , ctx = sc.ctx :> q + , names = sc.names :> x + , bound = sc.bound :> v + , used = Set.insert x sc.used + } + (x, v, sc') + +emptyNode :: Trie a +emptyNode = Node $ fromList [] + +cloArgName :: V.Clo a b -> Maybe Name +cloArgName (V.Clo x _) = Just x +cloArgName (V.CloConst _) = Nothing + +cache :: Path -> Scope -> V.El Theory -> (Trie Entity, Trie Definition, S.El Theory) +cache p sc v = do + let code u a = do + let sa = separate sc.len a + let cols = toList (sc.ctx :> sa) + let bound = toList (sc.bound :> V.local (FId sc.len)) + let boundStx = separate (sc.len + 1) <$> bound + let ent = Entity View (toList sc.names) ((.shape) <$> cols) (Just [0..sc.len]) + let tn = TableName sc.realm p + let def = Definition cols tn boundStx + let prop = S.Atom tn Nothing boundStx + let elt = S.Multi u $ S.Query sa.shape (S.Abs Nothing prop) + (Leaf ent, Node (fromList [("definition", Leaf def)]), elt) + case v of + V.LiftEl LSetTheory v -> (emptyNode, emptyNode, S.LiftEl (separate sc.len v)) + V.Code SSetU a -> code SSetU a + V.Code SPropU a -> code SSetU a + V.Lam SSetTheory dom clo -> do + let (x, arg, sc') = bind sc (cloArgName clo) dom + let (ents, defs, body) = cache p sc' (V.appClo clo arg) + (ents, defs, S.Lam (separate sc.len dom) (S.Abs (Just x) body)) + V.Cons fields -> do + let (ents, defs, fields') = + unzip3 [ cache (p :> x) sc field | (x, field) <- toList fields ] + ( Node (Dict fields.head (fromList ents)) + , Node (Dict fields.head (fromList defs)) + , S.Cons (Dict fields.head (fromList fields')) + ) diff --git a/packages/coln-compiler/src/Coln/SIR/Realm.hs b/packages/coln-compiler/src/Coln/SIR/Realm.hs index e95b7937..9fa4d60e 100644 --- a/packages/coln-compiler/src/Coln/SIR/Realm.hs +++ b/packages/coln-compiler/src/Coln/SIR/Realm.hs @@ -23,8 +23,8 @@ data Definition = Definition data Law = Law { inCtx :: [Query] - , antecedent :: Pred - , consequent :: Pred + , antecedent :: Prop + , consequent :: Prop } data Realm = Realm diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs index e671c91b..5c414434 100644 --- a/packages/coln-compiler/src/Coln/SIR/Separate.hs +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -35,9 +35,9 @@ separateClo n (V.CloConst body) = S.AbsConst (separate n body) instance Separate (V.El Theory) (S.El Theory) where separate n = \case V.LiftEl LSetTheory v -> S.LiftEl (separate n v) - V.Code SSetU a -> S.Multi (separate n a) - V.Code SPropU a -> S.Holds (asPred n a) - V.Lam SSetTheory clo -> S.Lam (separateClo n clo) + V.Code SSetU a -> S.Multi SSetU (separate n a) + V.Code SPropU a -> S.Multi SPropU (separate n a) + V.Lam SSetTheory dom clo -> S.Lam (separate n dom) (separateClo n clo) V.Cons fields -> S.Cons $ separate n <$> fields shapeOf :: V.Ty Set -> S.Shape @@ -53,33 +53,20 @@ shapeOf = \case V.BuiltinTy t -> S.BuiltinTy t V.Eq _ _ _ -> S.unitShape -predAt :: CtxLen -> V.Ty Set -> V.El Set -> S.Pred -predAt n = \case +propAt :: CtxLen -> V.Ty Set -> V.El Set -> S.Prop +propAt n = \case V.EltOf x args -> \v -> S.Atom x (Just (separate n v)) (separate n <$> args) V.Record rt -> \v -> do let go [] _ = [] go ((x, k):rest) vs = do let v' = V.proj v x - (x, predAt n (k vs) v') : (go rest (vs :> Pair SSet v')) + (x, propAt n (k vs) v') : (go rest (vs :> Pair SSet v')) S.And $ fromList $ go (toList rt.fieldTypes) rt.capture - V.BuiltinTy _ -> \_ -> S.truePred + V.BuiltinTy _ -> \_ -> S.trueProp V.Eq at lhs rhs -> \_ -> S.Eq (shapeOf at) (separate n lhs) (separate n rhs) -asPred :: CtxLen -> V.Ty Set -> S.Pred -asPred n = \case - V.EltOf x args -> S.Atom x Nothing (separate n <$> args) - V.Record rt -> do - let v = V.local (FId n) - let go [] _ = [] - go ((x, k):rest) vs = do - let v' = V.proj v x - (x, asPred n (k vs)) : (go rest (vs :> Pair SSet v')) - S.And $ fromList $ go (toList rt.fieldTypes) rt.capture - V.BuiltinTy _ -> S.truePred - V.Eq at lhs rhs -> S.Eq (shapeOf at) (separate n lhs) (separate n rhs) - instance Separate (V.Ty Set) S.Query where separate n a = - S.Query (shapeOf a) (S.Abs Nothing (predAt (n + 1) a (V.local (FId n)))) + S.Query (shapeOf a) (S.Abs Nothing (propAt (n + 1) a (V.local (FId n)))) diff --git a/packages/coln-compiler/src/Coln/SIR/Syntax.hs b/packages/coln-compiler/src/Coln/SIR/Syntax.hs index 99332be5..4c3a4a30 100644 --- a/packages/coln-compiler/src/Coln/SIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/SIR/Syntax.hs @@ -2,21 +2,21 @@ module Coln.SIR.Syntax where import Coln.Common import Coln.Core.Params +import Coln.MIR.Params data El :: MLevel -> Type where LiftEl :: El Set -> El Theory Var :: BId -> El Set Single :: Query -> El Set Proj :: El Set -> Name -> El Set - Holds :: Pred -> El Theory - Multi :: Query -> El Theory - Lam :: Abs (El Theory) -> El Theory + Multi :: SUniverse Set Theory -> Query -> El Theory + Lam :: Query -> Abs (El Theory) -> El Theory Cons :: Dict (El l) -> El l Lit :: Literal -> El Set -data Pred +data Prop = Atom TableName (Maybe (El Set)) [El Set] - | And (Dict Pred) + | And (Dict Prop) | Eq Shape (El Set) (El Set) data Shape @@ -27,8 +27,8 @@ data Shape unitShape :: Shape unitShape = Tuple (fromList []) -truePred :: Pred -truePred = And (fromList []) +trueProp :: Prop +trueProp = And (fromList []) data Abs a = Abs (Maybe Name) a @@ -36,6 +36,6 @@ data Abs a data Query = Query { shape :: Shape - , pred :: Abs Pred + , pred :: Abs Prop } From f4b0f7bbb9aa73d23f1440fd13f972d5e3ef797b Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Thu, 20 Aug 2026 14:39:07 +0100 Subject: [PATCH 04/42] flattening --- packages/coln-compiler/coln-compiler.cabal | 52 ++- packages/coln-compiler/src/Coln/Backend/IR.hs | 320 ------------- .../coln-compiler/src/Coln/Backend/Lower.hs | 421 ------------------ .../coln-compiler/src/Coln/Backend/MIR.hs | 12 - .../src/Coln/Backend/TypeScript/Assemble.hs | 52 ++- packages/coln-compiler/src/Coln/Common.hs | 5 + .../src/Coln/Elaborator/Rules/Initial.hs | 8 +- .../src/Coln/Elaborator/Rules/Variable.hs | 12 +- .../coln-compiler/src/Coln/FLIR/Flatten.hs | 127 ++++++ packages/coln-compiler/src/Coln/FLIR/Value.hs | 63 +++ .../coln-compiler/src/Coln/MIR/Evaluation.hs | 13 +- .../coln-compiler/src/Coln/MIR/Interpret.hs | 6 +- packages/coln-compiler/src/Coln/MIR/Layout.hs | 24 +- packages/coln-compiler/src/Coln/MIR/Memoed.hs | 4 +- packages/coln-compiler/src/Coln/MIR/Params.hs | 3 +- .../coln-compiler/src/Coln/MIR/Readback.hs | 6 +- packages/coln-compiler/src/Coln/MIR/Realm.hs | 2 +- packages/coln-compiler/src/Coln/MIR/Syntax.hs | 6 +- packages/coln-compiler/src/Coln/MIR/Value.hs | 5 +- packages/coln-compiler/src/Coln/SIR/Cache.hs | 23 +- .../coln-compiler/src/Coln/SIR/Separate.hs | 8 +- packages/coln-compiler/src/Coln/SIR/Syntax.hs | 11 +- 22 files changed, 323 insertions(+), 860 deletions(-) delete mode 100644 packages/coln-compiler/src/Coln/Backend/IR.hs delete mode 100644 packages/coln-compiler/src/Coln/Backend/Lower.hs delete mode 100644 packages/coln-compiler/src/Coln/Backend/MIR.hs create mode 100644 packages/coln-compiler/src/Coln/FLIR/Flatten.hs create mode 100644 packages/coln-compiler/src/Coln/FLIR/Value.hs diff --git a/packages/coln-compiler/coln-compiler.cabal b/packages/coln-compiler/coln-compiler.cabal index 958705d3..f5baa35b 100644 --- a/packages/coln-compiler/coln-compiler.cabal +++ b/packages/coln-compiler/coln-compiler.cabal @@ -10,12 +10,10 @@ build-type: Simple library exposed-modules: - -- Coln.Backend.IR - -- Coln.Backend.Lower - -- Coln.Backend.TypeScript.AST - -- Coln.Backend.TypeScript.Assemble - -- Coln.Backend.TypeScript.Generate - -- Coln.Backend.TypeScript.Params + Coln.Backend.TypeScript.AST + Coln.Backend.TypeScript.Assemble + Coln.Backend.TypeScript.Generate + Coln.Backend.TypeScript.Params Coln.Common Coln.Core Coln.Core.Conversion @@ -28,33 +26,39 @@ library Coln.Core.Syntax Coln.Core.Value Coln.Diagnostics - -- Coln.Elaborator.Coercion - -- Coln.Elaborator.Debug + Coln.Elaborator.Coercion + Coln.Elaborator.Debug Coln.Elaborator.Diagnostics - -- Coln.Elaborator.Environment - -- Coln.Elaborator.Judgment - -- Coln.Elaborator.Rules.Builtin - -- Coln.Elaborator.Rules.Equality - -- Coln.Elaborator.Rules.Function - -- Coln.Elaborator.Rules.Initial - -- Coln.Elaborator.Rules.Polarity - -- Coln.Elaborator.Rules.Record - -- Coln.Elaborator.Rules.Universe - -- Coln.Elaborator.Rules.Variable + Coln.Elaborator.Environment + Coln.Elaborator.Judgment + Coln.Elaborator.Rules.Builtin + Coln.Elaborator.Rules.Equality + Coln.Elaborator.Rules.Function + Coln.Elaborator.Rules.Initial + Coln.Elaborator.Rules.Polarity + Coln.Elaborator.Rules.Record + Coln.Elaborator.Rules.Universe + Coln.Elaborator.Rules.Variable + Coln.FLIR.Flatten + Coln.FLIR.Value Coln.Frontend.Diagnostics - -- Coln.Frontend.Notation - -- Coln.Frontend.Parser - -- Coln.Frontend.Parser.Expr - -- Coln.Frontend.Parser.Top - Coln.MIR.Interpret + Coln.Frontend.Notation + Coln.Frontend.Parser + Coln.Frontend.Parser.Expr + Coln.Frontend.Parser.Top Coln.MIR.Evaluation + Coln.MIR.Interpret + Coln.MIR.Layout + Coln.MIR.Memoed Coln.MIR.Params Coln.MIR.Readback + Coln.MIR.Realm Coln.MIR.Syntax Coln.MIR.Value + Coln.Report + Coln.SIR.Cache Coln.SIR.Separate Coln.SIR.Syntax - Coln.Report hs-source-dirs: src default-language: GHC2024 diff --git a/packages/coln-compiler/src/Coln/Backend/IR.hs b/packages/coln-compiler/src/Coln/Backend/IR.hs deleted file mode 100644 index afa4d3b9..00000000 --- a/packages/coln-compiler/src/Coln/Backend/IR.hs +++ /dev/null @@ -1,320 +0,0 @@ --- SPDX-FileCopyrightText: 2026 Coln contributors --- --- SPDX-License-Identifier: Apache-2.0 OR MIT -{-# LANGUAGE DeriveGeneric #-} -{-# OPTIONS_GHC -fno-warn-orphans #-} - -module Coln.Backend.IR where - --- XXX Lit/BultinTy should probably be moved up in the hierarchy -import Coln.Common -import Coln.Core.Params -import Coln.Core.Print -import Data.Aeson qualified as AE -import Data.Aeson.Encoding qualified as AE -import Data.Char (toLower) -import Data.Map.Ordered (OMap) -import Data.Map.Ordered qualified as OMap -import Data.Maybe (fromJust, fromMaybe) -import Data.Set qualified as Set -import Data.String (fromString) -import FNotation as N -import FNotation.Kinds as K -import GHC.Generics - -type ColName = Path - -data ColType - = RowId TableName - | BuiltinTy BuiltinTy - deriving (Show, Eq, Generic) - -data Materialization - = Recomputed - | Memoized - | Materialized - deriving (Show, Eq, Generic) - -data IndexMethod - = BTree - deriving (Show, Eq, Generic) - -data EntityVariant - = Table - | View Materialization - | Index IndexMethod [ColName] - deriving (Show, Eq, Generic) - -data Entity = Entity - { entityVariant :: EntityVariant - , -- , columns :: Trie ColType - columns :: [(ColName, ColType)] - , primaryKey :: Maybe (Set.Set ColName) - } - deriving (Show, Eq, Generic) - -data Term - = Lit Literal - | Var FId - deriving (Show, Eq, Generic) - -data Atom = Atom - { entity :: TableName - , rowId :: Maybe Term - , values :: OMap Int Term - } - deriving (Show, Eq, Generic) - -data Prop - = PAtom Atom - | PEq Term Term - deriving (Show, Eq, Generic) - -data RuleVariant = Chased | Enforced | Monitored - deriving (Show, Eq, Generic) - -data Rule = Rule - { ruleVariant :: RuleVariant - , varNames :: Bwd ColName - , varTypes :: Bwd ColType - , antecedents :: [Prop] - , consequents :: [Prop] - } - deriving (Show, Eq, Generic) - -data FlatRealm = FlatRealm - { entities :: OMap TableName Entity - , rules :: OMap TableName Rule - } - deriving (Show, Eq, Generic) - -emptyFlatRealm :: FlatRealm -emptyFlatRealm = FlatRealm OMap.empty OMap.empty - --- JSON --------------------------------------------------------------------------------- - -aeOptions :: AE.Options -aeOptions = - AE.defaultOptions - { AE.allNullaryToStringTag = False - , AE.constructorTagModifier = \x -> fmap toLower (take 1 x) ++ (drop 1 x) - } - -class PathLike a where - namesOf :: a -> [Name] - -encName :: Name -> AE.Encoding -encName n = AE.list AE.toEncoding $ n.init ++ [n.last] - -encPath :: (PathLike a) => a -> AE.Encoding -encPath = AE.list encName . namesOf - -instance PathLike Path where namesOf = toList - -instance PathLike TableName where namesOf tn = tn.realm : namesOf tn.path - -pathMapEncoding :: (PathLike k) => (a -> AE.Encoding) -> OMap k a -> AE.Encoding -pathMapEncoding f = AE.list (\(k, v) -> AE.pairs $ AE.pair "path" (encPath k) <> AE.pair "value" (f v)) . OMap.assocs - -taggedEncoding :: Text -> AE.Series -> AE.Encoding -taggedEncoding t v = AE.pairs $ AE.pair "tag" (AE.toEncoding t) <> v - -instance AE.ToJSON ColType where - toJSON = panic "aesons behaving badly" - toEncoding = \case - RowId e -> taggedEncoding "rowId" $ AE.pair "path" $ encPath e - BuiltinTy bt -> taggedEncoding "builtin" $ AE.pair "type" $ AE.genericToEncoding aeOptions{AE.allNullaryToStringTag = True} bt - -instance AE.ToJSON Materialization where - toEncoding = AE.genericToEncoding aeOptions{AE.allNullaryToStringTag = True} - -instance AE.ToJSON IndexMethod where - toEncoding = AE.genericToEncoding aeOptions{AE.allNullaryToStringTag = True} - -instance AE.ToJSON EntityVariant where - toJSON = panic "aesons behaving badly" - toEncoding = \case - Table -> taggedEncoding "table" $ mempty - View m -> taggedEncoding "view" $ AE.pair "materialization" $ AE.toEncoding m - Index m cs -> taggedEncoding "index" $ AE.pair "method" (AE.toEncoding m) <> AE.pair "columns" (AE.list encPath cs) - -instance AE.ToJSON Entity where - toJSON = panic "aesons behaving badly" - toEncoding e = - AE.pairs $ - mconcat - [ AE.pair "entityVariant" $ AE.toEncoding e.entityVariant - , AE.pair "columns" $ AE.list (\(k, v) -> AE.pairs $ AE.pair "path" (encPath k) <> AE.pair "type" (AE.toEncoding v)) e.columns - , AE.pair "primaryKey" $ fromMaybe AE.null_ $ fmap (AE.list encPath) $ fmap Set.toAscList e.primaryKey - ] - -instance AE.ToJSON Term where - toJSON = panic "aesons behaving badly" - toEncoding = \case - Lit l -> taggedEncoding "lit" $ AE.pair "lit" $ case l of - LitInt i -> taggedEncoding "int" $ AE.pair "value" $ AE.toEncoding i - LitString s -> taggedEncoding "string" $ AE.pair "value" $ AE.toEncoding s - Var (FId i) -> taggedEncoding "var" $ AE.pair "index" $ AE.toEncoding i - -instance AE.ToJSON Atom where - toJSON = panic "aesons behaving badly" - toEncoding a = - AE.pairs $ - mconcat - [ AE.pair "entity" $ encPath a.entity - , AE.pair "rowId" $ AE.toEncoding a.rowId - , AE.pair "values" $ AE.list (\(k, v) -> AE.pairs $ AE.pair "column" (AE.toEncoding k) <> AE.pair "term" (AE.toEncoding v)) $ OMap.assocs a.values - ] - -instance AE.ToJSON Prop where - toEncoding = \case - PAtom a -> taggedEncoding "atom" $ AE.pair "atom" $ AE.toEncoding a - PEq l r -> taggedEncoding "eq" $ AE.pair "left" (AE.toEncoding l) <> AE.pair "right" (AE.toEncoding r) - -instance AE.ToJSON RuleVariant where - toEncoding = AE.genericToEncoding aeOptions{AE.allNullaryToStringTag = True} - -instance AE.ToJSON Rule where - toJSON = panic "aesons behaving badly" - toEncoding r = - AE.pairs $ - mconcat - [ AE.pair "ruleVariant" $ AE.toEncoding r.ruleVariant - , AE.pair "varNames" $ AE.list encPath $ toList r.varNames - , AE.pair "varTypes" $ AE.list AE.toEncoding $ toList r.varTypes - , AE.pair "antecedents" $ AE.toEncoding r.antecedents - , AE.pair "consequents" $ AE.toEncoding r.consequents - ] - -instance AE.ToJSON FlatRealm where - toJSON = panic "aesons behaving badly" - toEncoding fr = AE.pairs $ AE.pair "entities" (pathMapEncoding AE.toEncoding fr.entities) <> AE.pair "rules" (pathMapEncoding AE.toEncoding fr.rules) - --- Pretty-printer --------------------------------------------------------------------------------- - -entityVariantDeclKeyword :: EntityVariant -> Name -entityVariantDeclKeyword e = Name [] $ fromString $ case e of - Table -> "table" - View _ -> "view" -- TODO - Index _ _ -> "index" -- TODO - -ruleVariantDeclKeyword :: RuleVariant -> Name -ruleVariantDeclKeyword e = Name [] $ fromString $ case e of - Chased -> "chased" - Enforced -> "enforced" - Monitored -> "monitored" - -toNotationColName :: ColName -> N.Ntn0 -toNotationColName BwdNil = N.Tuple [] () -- Shouldn't happen -toNotationColName (BwdNil :> x) = N.Field x () -toNotationColName (p :> x) = N.Juxt (toNotationColName p) (N.Field x ()) - -instance ToNotationTop Path where - toNotationTop BwdNil = N.Tuple [] () -- Shouldn't happen - toNotationTop (BwdNil :> x) = N.Ident x () - toNotationTop (p :> x) = N.Juxt (toNotationTop p) (N.Field x ()) - -instance ToNotationTop TableName where - toNotationTop tn = foldl (\n p -> N.Juxt n (N.Field p ())) (N.Ident "ℜ" ()) tn.path - -instance ToNotationTop ColType where - toNotationTop = \case - RowId e -> toNotationTop e - BuiltinTy bt -> N.Keyword (fromString $ show bt) () - -instance ToNotationTop (ColName, ColType) where - toNotationTop (n, t) = N.Infix (toNotationColName n) (N.Keyword ":" ()) (toNotationTop t) - -instance ToNotationTop (TableName, Entity) where - toNotationTop (tn, e) = do - let keyword = entityVariantDeclKeyword e.entityVariant - let cols = N.Tuple (map toNotationTop e.columns) () - let colsWKey = case e.primaryKey of - Nothing -> cols - Just primaryKey -> N.Infix cols (N.Keyword "primarykey" ()) (N.Tuple (map toNotationColName $ Set.toList primaryKey) ()) - N.Decl keyword (N.Infix (toNotationTop tn) (N.Keyword ":=" ()) colsWKey) () - -instance ToNotationTop Literal where - toNotationTop = \case - LitInt i -> N.Int i () - LitString t -> N.String t () - -toNotationTerm :: Bwd ColName -> Term -> N.Ntn0 -toNotationTerm _ (Lit l) = toNotationTop l -toNotationTerm cs (Var i) = toNotationTop (elemAt (rev cs) i) -- TODO: Why does Rule use Bwd and FId together? - -toNotationAtom :: OMap TableName [ColName] -> Bwd ColName -> Atom -> N.Ntn0 -toNotationAtom columnNames cs a = do - let entity = toNotationTop a.entity - let cols = fromJust (OMap.lookup a.entity columnNames) - let field (i, t) = N.Infix (toNotationColName (cols !! i)) (N.Keyword "↦" ()) (toNotationTerm cs t) - let body = N.Juxt entity $ N.Tuple (field <$> OMap.assocs a.values) () - case a.rowId of - Nothing -> body - Just r -> N.Infix (toNotationTerm cs r) (N.Keyword "∈" ()) body - -toNotationProp :: OMap TableName [ColName] -> Bwd ColName -> Prop -> N.Ntn0 -toNotationProp ts cs = \case - PAtom a -> toNotationAtom ts cs a - PEq a b -> N.Infix (toNotationTerm cs a) (N.Keyword "=" ()) (toNotationTerm cs b) - -toNotationConjunction :: [N.Ntn0] -> N.Ntn0 -toNotationConjunction [] = N.Keyword "⊤" () -toNotationConjunction [p] = p -toNotationConjunction (p : ps) = N.Infix p (N.Keyword "∧" ()) (toNotationConjunction ps) - -toNotationRule :: OMap TableName [ColName] -> (TableName, Rule) -> N.Ntn0 -toNotationRule columnNames (tn, r) = do - let keyword = ruleVariantDeclKeyword r.ruleVariant - let head = foldl' N.Juxt (toNotationTop tn) (fmap toNotationTop (toList r.varNames)) - let ante = toNotationConjunction $ fmap (toNotationProp columnNames r.varNames) r.antecedents - let cons = toNotationConjunction $ fmap (toNotationProp columnNames r.varNames) r.consequents - let seq = N.Infix ante (N.Keyword "⊢" ()) cons - N.Decl keyword (N.Infix head (N.Keyword ":=" ()) seq) () - -instance ToNotationTop FlatRealm where - toNotationTop (FlatRealm es rs) = do - let nes = N.Block "entities" Nothing (fmap toNotationTop (OMap.assocs es)) () - let columnNames = fmap (fmap fst . (.columns)) es - let nrs = N.Block "rules" Nothing (fmap (toNotationRule columnNames) (OMap.assocs rs)) () - N.Block "flatrealm" Nothing [nes, nrs] () - -irLexConfig :: N.ConfTable Kind -irLexConfig = - confTableFromList - [ ("flatrealm", K.Block) - , ("entities", K.Block) - , ("rules", K.Block) - , ("table", K.Decl) - , ("view", K.Decl) - , ("index", K.Decl) - , ("chased", K.Decl) - , ("enforced", K.Decl) - , ("monitored", K.Decl) - , ("end", K.End) - , (":=", K.SKeyword) - , ("=", K.SKeyword) - , (":", K.SKeyword) - , ("∈", K.SKeyword) - , ("∧", K.SKeyword) - , ("⊢", K.SKeyword) - , ("↦", K.SKeyword) - , ("⊤", K.SKeyword) - ] - -irParseConfig :: N.ConfTable N.Prec -irParseConfig = - confTableFromList - [ (":=", Prec 10 AssocNon) - , (":", Prec 20 AssocNon) - , ("⊢", Prec 30 AssocNon) - , ("∧", Prec 35 AssocR) - , ("=", Prec 40 AssocNon) - , ("∈", Prec 45 AssocNon) - , ("↦", Prec 60 AssocNon) - ] - -instance DPretty FlatRealm where - dpretty r = N.dprettyWithConfigs irParseConfig irLexConfig $ toNotationTop r diff --git a/packages/coln-compiler/src/Coln/Backend/Lower.hs b/packages/coln-compiler/src/Coln/Backend/Lower.hs deleted file mode 100644 index c0a72346..00000000 --- a/packages/coln-compiler/src/Coln/Backend/Lower.hs +++ /dev/null @@ -1,421 +0,0 @@ --- SPDX-FileCopyrightText: 2026 Coln contributors --- --- SPDX-License-Identifier: Apache-2.0 OR MIT - -module Coln.Backend.Lower where - -import Control.Arrow (first, second) -import Control.Monad (forM_) -import Data.Aeson qualified as AE -import Data.Foldable qualified as F -import Data.Map.Ordered (OMap, (>|)) -import Data.Map.Ordered qualified as OMap -import Data.Set qualified as Set -import Data.Traversable (mapAccumL) -import Prettyprinter.Render.Text (hPutDoc) -import System.FilePath (()) -import System.IO (IOMode (..), withFile) -import Prelude hiding (lookup) - -import Coln.Backend.IR qualified as I -import Coln.Common -import Coln.Core.Evaluation -import Coln.Core.Globals qualified as C -import Coln.Core.Params -import Coln.Core.Syntax qualified as S -import Coln.Core.Value qualified as V - -data Shape - = RowId TableName - | BuiltinTy BuiltinTy - | Tuple (Dict Shape) - | Unit - deriving (Show) - -data Term - = Var BId - | Lookup TableName (Dict Term) - | Cons (Dict Term) - | Proj Term Name - | Lit Literal - deriving (Show) - -data Pred - = EltOf Term TableName (Dict Term) - | And (Dict Pred) - | Equal Term Term - | PTrue - deriving (Show) - -type CtxLen = Int - -class Lower a b | a -> b where - lower :: CtxLen -> a -> b - -instance Lower V.Head Term where - lower n (V.LocalVar (FId i)) = Var (BId (n - i - 1)) - lower _ (V.GlobalVar _ _) = panic "not fully evaluated" - lower n (V.Lookup x ts _) = Lookup x (lower n <$> ts) - -instance Lower V.Spine (Term -> Term) where - lower n = \case - V.Id -> \t -> t - V.App _ _ -> panic "not fully laid out" - V.Proj sp x -> \t -> Proj (lower n sp t) x - -instance Lower V.Neutral Term where - lower n ne = case ne.expansion of - V.IntoCons fields -> Cons (lower n <$> fields) - V.NotApplicable -> lower n ne.spine $ lower n ne.head - -instance Lower (V.El N) Term where - lower :: CtxLen -> V.El N -> Term - lower n = \case - V.Neu ne -> lower n ne - V.InitNeu _ -> panic "can't lower init yet" - V.Code _ -> panic "non set-level term" - V.Lam _ _ -> panic "non set-level term" - V.Cons ds -> Cons (lower n <$> ds) - V.Lit l -> Lit l - -data Ty = Ty - { shape :: Shape - , pred :: Pred - } - deriving (Show) - -separate :: CtxLen -> V.Ty N -> V.El N -> Ty -separate n = \case - V.U _ -> panic "lowering non-set-level type: U" - V.Decode ne -> case ne.description of - Just (V.Record rt) -> \v -> do - let go :: V.Locals -> [(Name, V.Locals -> V.Ty N)] -> [(Shape, Pred)] - go _ [] = [] - go vs ((x, f) : rest) = do - let a = f vs - let v' = V.proj v x - let t = separate n a v' - (t.shape, t.pred) : go (V.LSnoc vs v') rest - let (shapes, props) = unzip $ go rt.capture (toList rt.fieldTypes) - Ty (Tuple (withHead rt.fieldTypes shapes)) (And (withHead rt.fieldTypes props)) - Nothing -> panic "lowering neutral type" - V.InitDecode _ -> panic "can't lower init yet" - V.Function _ -> panic "lowering non-set-level type: Function" - V.Eq et -> \_ -> Ty Unit (Equal (lower n et.lhs) (lower n et.rhs)) - V.BuiltinTy t -> \_ -> Ty (BuiltinTy t) PTrue - V.EltOf x ts -> \v -> Ty (RowId x) (EltOf (lower n v) x (lower n <$> ts)) - -data Generator - = Rel [Name] [Ty] - | Fun [Name] [Ty] Ty - -lowerAtFresh :: CtxLen -> V.Ty N -> Ty -lowerAtFresh n a = separate (n + 1) a (V.local (FId n) a) - -lowerTele :: [S.Ty N] -> ([Ty], V.Locals) -lowerTele = go V.LNil 0 - where - go vs _ [] = ([], vs) - go vs n (t : ts) = do - let a = eval vs t - let v = V.local (FId n) a - let (ts', vs') = go (V.LSnoc vs v) (n + 1) ts - (separate (n + 1) a v : ts', vs') - -lowerGen :: C.Generator -> Generator -lowerGen (C.Fun xs ts t) = do - let (ts', vs) = lowerTele ts - Fun xs ts' (lowerAtFresh (length ts) (eval vs t)) -lowerGen (C.Rel xs ts) = do - let (ts', _) = lowerTele ts - Rel xs ts' - -type EnvTerm = Trie I.Term - -noTerms :: EnvTerm -noTerms = Node $ fromList [] - -data LocalCtx = LocalCtx - { localLen :: CtxLen - , totalLen :: CtxLen - , localNames :: Bwd I.ColName - , localTys :: Bwd I.ColType - , conditions :: Bwd I.Prop - } - -data RuleFragment = RuleFragment - { ruleCtx :: LocalCtx - , heads :: [(I.ColName, I.Prop)] - } - -data DisaggState = DisaggState - { funShapes :: OMap TableName Shape - , oldLen :: CtxLen - , oldNames :: Bwd Name - , oldTys :: Bwd Ty - , oldEnv :: Bwd EnvTerm - , newLen :: CtxLen - , newNames :: Bwd I.ColName - , newTys :: Bwd I.ColType - , frags :: Bwd RuleFragment - } - -data PredState = PredState - { parent :: DisaggState - , localCtx :: LocalCtx - } - -steal :: Bwd a -> CtxLen -> Bwd a -> Bwd a -steal base 0 _ = base -steal base n (xs :> x) = steal base (n - 1) xs :> x -steal _ _ _ = panic "not enough local variables" - -renumberTerm :: (Int -> Int) -> I.Term -> I.Term -renumberTerm f (I.Var (FId i)) = I.Var . FId $ f i -renumberTerm _ x = x - -renumberProp :: (Int -> Int) -> I.Prop -> I.Prop -renumberProp f (I.PAtom atom) = - I.PAtom $ - atom - { I.rowId = fmap (renumberTerm f) atom.rowId - , I.values = fmap (renumberTerm f) atom.values - } -renumberProp f (I.PEq lhs rhs) = - I.PEq - (renumberTerm f lhs) - (renumberTerm f rhs) - --- the global variables of the second must be a prefix of the global variables --- of the first -mergeFrag :: RuleFragment -> RuleFragment -> RuleFragment -mergeFrag base add = do - let basec = base.ruleCtx - let addc = add.ruleCtx - let renum n = if n >= addc.totalLen - addc.localLen then n - addc.totalLen + addc.localLen + basec.totalLen else n - RuleFragment - { ruleCtx = - LocalCtx - { localLen = basec.localLen + addc.localLen - , totalLen = basec.totalLen + addc.localLen - , localNames = steal basec.localNames addc.localLen addc.localNames - , localTys = steal basec.localTys addc.localLen addc.localTys - , conditions = basec.conditions <> fmap (renumberProp renum) addc.conditions - } - , heads = base.heads ++ fmap (second $ renumberProp renum) add.heads - } - -pushNew :: DisaggState -> (I.ColName, I.ColType) -> (DisaggState, EnvTerm) -pushNew ds (cn, ct) = do - let et = Leaf $ I.Var $ FId $ ds.newLen - let ds' = - ds - { newLen = ds.newLen + 1 - , newNames = ds.newNames :> cn - , newTys = ds.newTys :> ct - } - (ds', et) - -pushShape :: DisaggState -> (I.ColName, Shape) -> (DisaggState, EnvTerm) -pushShape ds = uncurry $ \x -> \case - RowId y -> pushNew ds (x, I.RowId y) - BuiltinTy bt -> pushNew ds (x, I.BuiltinTy bt) - Tuple d -> second (Node . withHead d) . mapAccumL pushShape ds . fmap (first (x :>)) $ toList d - Unit -> (ds, noTerms) - -pushOld :: DisaggState -> (Name, Ty, EnvTerm) -> DisaggState -pushOld ds (x, ty, et) = ds{oldLen = ds.oldLen + 1, oldNames = ds.oldNames :> x, oldTys = ds.oldTys :> ty, oldEnv = ds.oldEnv :> et} - -openPred :: DisaggState -> PredState -openPred ds = - PredState ds $ - LocalCtx - { localLen = 0 - , totalLen = ds.newLen - , localNames = ds.newNames - , localTys = ds.newTys - , conditions = BwdNil - } - -pushFrag :: PredState -> I.ColName -> [I.Prop] -> DisaggState -pushFrag ps x h = ps.parent{frags = ps.parent.frags :> RuleFragment ps.localCtx (fmap (\y -> (x, y)) h)} - -pushLocal :: PredState -> (I.ColName, I.ColType) -> (PredState, EnvTerm) -pushLocal ps (cn, ct) = do - let et = Leaf $ I.Var $ FId $ ps.localCtx.totalLen - let ctx' = - ps.localCtx - { localLen = ps.localCtx.localLen + 1 - , totalLen = ps.localCtx.totalLen + 1 - , localNames = ps.localCtx.localNames :> cn - , localTys = ps.localCtx.localTys :> ct - } - (ps{localCtx = ctx'}, et) - -pushVars :: PredState -> (I.ColName, Shape) -> (PredState, EnvTerm) -pushVars ps = uncurry $ \x -> \case - RowId tn -> pushLocal ps (x, I.RowId tn) - BuiltinTy bt -> pushLocal ps (x, I.BuiltinTy bt) - Tuple d -> second (Node . withHead d) . mapAccumL pushVars ps . fmap (first (x :>)) $ toList d - Unit -> (ps, noTerms) - -pushTerm' :: PredState -> (I.ColName, Term) -> (PredState, Trie I.Term) -pushTerm' ps = uncurry $ \x -> \case - Var b -> (ps, elemAt ps.parent.oldEnv b) - Lookup tn d -> case OMap.lookup tn ps.parent.funShapes of - Nothing -> panic "unknown function" - Just s -> do - let (ps', ts) = pushVars ps (x, s) - let ps'' = pushCond ps' x tn d ts - (ps'', ts) - Cons d -> second (Node . withHead d) . mapAccumL pushTerm' ps . fmap (first (x :>)) $ toList d - Proj y f -> do - let (ps', ts) = pushTerm' ps (x, y) - case ts of - Leaf _ -> panic "projection of non-record value" - Node d -> case lookup d f of - Nothing -> panic "nonexistent field" - Just z -> (ps', z) - Lit l -> (ps, Leaf $ I.Lit l) - -pushTerm :: PredState -> (I.ColName, Term) -> (PredState, [I.Term]) -pushTerm ps a = second F.toList $ pushTerm' ps a - -pushCond :: PredState -> I.ColName -> TableName -> Dict Term -> Trie I.Term -> PredState -pushCond ps x tn d ts' = do - let (ps', ts) = mapAccumL pushTerm ps . fmap (first (x :>)) $ toList d - let c = I.PAtom . I.Atom tn Nothing . OMap.fromList . zip [0 ..] $ foldr (++) (F.toList ts') ts - ps'{localCtx = ps'.localCtx{conditions = ps'.localCtx.conditions :> c}} - --- XXX actual state monad? -pushPred :: DisaggState -> (I.ColName, Pred) -> DisaggState -pushPred ds = uncurry $ \x -> \case - EltOf t n ts -> do - let ps1 = openPred ds - let (ps2, elts) = pushTerm' ps1 (x, t) - let elt = case elts of Leaf x -> x; _ -> panic "EltOf lhs was not an entity" - let (ps3, fields) = mapAccumL pushTerm ps2 . fmap (first (x :>)) $ toList ts - let fields' = OMap.fromList . zip [0 ..] $ concat fields - pushFrag ps3 x [I.PAtom $ I.Atom n (Just elt) fields'] - And d -> foldl' pushPred ds . fmap (first (x :>)) $ toList d - Equal lhs rhs -> do - let ps = openPred ds - let (ps', lhs') = pushTerm ps (x :> "lhs", lhs) - let (ps'', rhs') = pushTerm ps' (x :> "rhs", rhs) - pushFrag ps'' x $ zipWith I.PEq lhs' rhs' - PTrue -> ds - -pushTy :: DisaggState -> (Name, Ty) -> DisaggState -pushTy ds (x, ty) = do - let (ds', et) = pushShape ds (BwdNil :> x, ty.shape) - let ds'' = pushOld ds' (x, ty, et) - pushPred ds'' (BwdNil :> x, ty.pred) - -disaggregateTele :: OMap TableName Shape -> [Name] -> [Ty] -> DisaggState -disaggregateTele fs xs tys = do - let ds = - DisaggState - { funShapes = fs - , oldLen = 0 - , oldNames = BwdNil - , oldTys = BwdNil - , oldEnv = BwdNil - , newLen = 0 - , newNames = BwdNil - , newTys = BwdNil - , frags = BwdNil - } - foldl' pushTy ds $ zip xs tys - -mergeFrags :: DisaggState -> RuleFragment -mergeFrags ds = do - let base = - RuleFragment - { ruleCtx = - LocalCtx - { localLen = 0 - , totalLen = ds.newLen - , localNames = ds.newNames - , localTys = ds.newTys - , conditions = BwdNil - } - , heads = [] - } - foldl' mergeFrag base $ toList ds.frags - -disaggregateGen :: OMap TableName Shape -> TableName -> Generator -> I.FlatRealm -> I.FlatRealm -disaggregateGen fs tn (Rel xs ts) fr = do - let ds = disaggregateTele fs xs ts - let rf = mergeFrags ds - let foreignKey = - I.Rule - { I.ruleVariant = I.Enforced - , I.varNames = rf.ruleCtx.localNames - , I.varTypes = rf.ruleCtx.localTys - , I.antecedents = (I.PAtom $ I.Atom tn Nothing $ OMap.fromList $ map (\n -> (n, I.Var $ FId n)) [0 .. ds.newLen - 1]) : toList rf.ruleCtx.conditions - , I.consequents = fmap snd rf.heads - } - let table = - I.Entity - { I.entityVariant = I.Table - , I.columns = zip (toList ds.newNames) (toList ds.newTys) - , primaryKey = Nothing - } - fr - { I.entities = fr.entities >| (tn, table) - , I.rules = fr.rules >| (tn{path = tn.path :> "foreignKey"}, foreignKey) - } -disaggregateGen fs tn (Fun xs ts t) fr = do - let ds = disaggregateTele fs xs ts - let rf = mergeFrags ds - let totality = - I.Rule - { I.ruleVariant = I.Monitored -- XXX do Enforced when appropriate - , I.varNames = rf.ruleCtx.localNames - , I.varTypes = rf.ruleCtx.localTys - , I.antecedents = toList rf.ruleCtx.conditions ++ fmap snd rf.heads - , I.consequents = [I.PAtom $ I.Atom tn Nothing $ OMap.fromList $ map (\n -> (n, I.Var $ FId n)) [0 .. ds.newLen - 1]] - } - let x = freshNameFor xs - let ds' = pushTy ds (x, t) - let rf' = mergeFrags ds' - let foreignKey = - I.Rule - { I.ruleVariant = I.Enforced - , I.varNames = rf'.ruleCtx.localNames - , I.varTypes = rf'.ruleCtx.localTys - , I.antecedents = (I.PAtom $ I.Atom tn Nothing $ OMap.fromList $ map (\n -> (n, I.Var $ FId n)) [0 .. ds'.newLen - 1]) : toList rf'.ruleCtx.conditions - , I.consequents = fmap snd rf'.heads - } - let table = - I.Entity - { I.entityVariant = I.Table - , I.columns = zip (toList ds'.newNames) (toList ds'.newTys) - , I.primaryKey = Just . Set.fromList $ toList ds.newNames - } - fr - { I.entities = fr.entities >| (tn, table) - , I.rules = fr.rules >| (tn{path = tn.path :> "foreignKey"}, foreignKey) >| (tn{path = tn.path :> "total"}, totality) - } - -lowerRealm :: Name -> C.Realm -> I.FlatRealm -lowerRealm realmName r = go OMap.empty I.emptyFlatRealm (toList r.generators) - where - go _ fr [] = fr - go fs fr ((xs, g) : rest) = do - let tn = TableName realmName xs - let lg = lowerGen g - let fr' = disaggregateGen fs tn lg fr - let fs' = case lg of - Fun _ _ t -> fs >| (tn, t.shape) - _ -> fs - go fs' fr' rest - -writeIRFor :: C.Globals -> FilePath -> IO () -writeIRFor ge fp = do - forM_ (OMap.assocs ge.realms) $ \(x, r) -> do - let fr = lowerRealm x r - let fn = fp mangleToString x <> ".json" - AE.encodeFile fn fr - let pn = fp mangleToString x <> ".pretty" - withFile pn WriteMode (\h -> hPutDoc h (dpretty fr)) diff --git a/packages/coln-compiler/src/Coln/Backend/MIR.hs b/packages/coln-compiler/src/Coln/Backend/MIR.hs deleted file mode 100644 index 1c52618c..00000000 --- a/packages/coln-compiler/src/Coln/Backend/MIR.hs +++ /dev/null @@ -1,12 +0,0 @@ --- | MIR stands for "model intermediate representation" --- it is for expressing *models* of theories, possibly in the context of free --- variables which are set-level. -module Coln.Backend.MIR where - --- If layout is Core -> MIR, then we need MIR values as well as MIR syntax. - --- Specifically, this is because layout will have to be MIR value -> MIR syntax. - -data El - = Var BId - | diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Assemble.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Assemble.hs index efb12c05..d82161e7 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Assemble.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Assemble.hs @@ -46,7 +46,7 @@ instance Assemble Ty where asm (ListTy a) = asm a <> "[]" instance Assemble Binding where - asm b = asm b.name <> ":" <+> asm b.ty + asm b = asm b . name <> ":" <+> asm b . ty instance Assemble BinOp where asm EqualsEquals = "==" @@ -85,52 +85,62 @@ instance Assemble Statement where instance Assemble Block where asm b = - let ret = case b.return of + let ret = case b . return of Just t -> ["return" <+> asm t <> ";"] Nothing -> [] - in hardBlocked $ (asm <$> b.statements) ++ ret + in hardBlocked $ (asm <$> b . statements) ++ ret instance Assemble Class where asm c = "class" - <+> asm c.name - <> maybe mempty (\e -> " extends" <+> asm e) c.extends - <> maybe mempty (\i -> " implements" <+> asm i) c.implements + <+> asm c + . name + <> maybe mempty (\e -> " extends" <+> asm e) c . extends + <> maybe mempty (\i -> " implements" <+> asm i) c + . implements <+> hardBlocked ( punctuate line - [ vsep [asm f <> ";" | f <- c.fields] - , asm c.constructor + [ vsep [asm f <> ";" | f <- c . fields] + , asm c . constructor ] ) instance Assemble Constructor where asm c = "constructor" - <> tupled (asm <$> c.args) - <+> asm c.body + <> tupled (asm <$> c . args) + <+> asm c + . body instance Assemble Interface where asm i = "interface" - <+> asm i.name - <+> maybe mempty (\e -> "extends" <+> asm e <> " ") i.extends - <> hardBlocked [asm f <> ";" | f <- i.fields] + <+> asm i + . name + <+> maybe mempty (\e -> "extends" <+> asm e <> " ") i + . extends + <> hardBlocked [asm f <> ";" | f <- i . fields] instance Assemble FunctionDef where asm f = "function" - <+> asm f.name - <> tupled (asm <$> f.args) - <> maybe mempty (\ty -> ":" <+> asm ty) f.ret - <+> asm f.body + <+> asm f + . name + <> tupled (asm <$> f . args) + <> maybe mempty (\ty -> ":" <+> asm ty) f + . ret + <+> asm f + . body instance Assemble TypeDef where asm td = "type" - <+> asm td.name + <+> asm td + . name <+> "=" - <+> asm td.body + <+> asm td + . body <> ";" instance (Assemble a) => Assemble (AccessControlled a) where @@ -159,7 +169,7 @@ instance Assemble Import where instance Assemble Module where asm m = vsep - [ vsep $ asm <$> m.imports + [ vsep $ asm <$> m . imports , "" - , vsep $ punctuate line $ asm <$> m.declarations + , vsep $ punctuate line $ asm <$> m . declarations ] diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index 066b84a5..daaa4502 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -9,6 +9,7 @@ module Coln.Common ( module Data.Map.Ordered, module Data.Kind, module Data.Vector.Strict, + module Data.Void, module Data.Text, module Prettyprinter, module Coln.Report, @@ -58,6 +59,7 @@ import Data.Text (Text) import Data.Traversable hiding (for) import Data.Vector.Strict (Vector) import Data.Vector.Strict qualified as V +import Data.Void import Diagnostician import FNotation (Name (..)) import Prettyprinter (Pretty (..), defaultLayoutOptions, layoutPretty, (<+>)) @@ -108,6 +110,9 @@ class Contains a i | a -> i where class ToList a e | a -> e where toList :: a -> [e] +instance ToList (V.Vector a) a where + toList = V.toList + class FromList a e | a -> e where fromList :: [e] -> a diff --git a/packages/coln-compiler/src/Coln/Elaborator/Rules/Initial.hs b/packages/coln-compiler/src/Coln/Elaborator/Rules/Initial.hs index b2fc2919..9a961988 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Rules/Initial.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Rules/Initial.hs @@ -13,10 +13,10 @@ import Coln.Elaborator.Judgment create :: Span -> Typ N -> Syn D create sp t = Syn \e -> do - case e.scope.mode of + case e . scope . mode of Inductive -> pure () Conjunctive -> do let msg = "cannot create initial model in conjunctive mode" - failWith e.diagEnv sp InitInConjunctive msg - a <- t.elab (e{scope = lock e.scope, target = TargetAnonymous}) - pure (a.val, init a) + failWith e . diagEnv sp InitInConjunctive msg + a <- t . elab (e{scope = lock e . scope, target = TargetAnonymous}) + pure (a . val, init a) diff --git a/packages/coln-compiler/src/Coln/Elaborator/Rules/Variable.hs b/packages/coln-compiler/src/Coln/Elaborator/Rules/Variable.hs index b1051f9c..4d55abd4 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Rules/Variable.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Rules/Variable.hs @@ -15,15 +15,15 @@ import Coln.Elaborator.Judgment find :: Span -> Name -> Syn N find sp x = Syn \e -> do - (ty, tm, m) <- case lookup e.scope x of + (ty, tm, m) <- case lookup e . scope x of Just (i, v, ty, m) -> pure (ty, localVar i v, m) - Nothing -> case lookup e.globals x of - Just ge -> pure (ge.ty, globalVar x ge.reflected, ge.mode) + Nothing -> case lookup e . globals x of + Just ge -> pure (ge . ty, globalVar x ge . reflected, ge . mode) Nothing -> do let msg = "no such variable" <+> dpretty x <+> "in scope" - failWith e.diagEnv sp VariableNotInScope msg - case (m, e.scope.mode) of + failWith e . diagEnv sp VariableNotInScope msg + case (m, e . scope . mode) of (Inductive, Conjunctive) -> do let msg = "cannot use inductively bound variable in a conjunctive context" - failWith e.diagEnv sp InductiveInConjunctive msg + failWith e . diagEnv sp InductiveInConjunctive msg _ -> pure (ty, tm) diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs new file mode 100644 index 00000000..744c79b7 --- /dev/null +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -0,0 +1,127 @@ +module Coln.FLIR.Flatten where + +import Coln.Common +import Coln.Core.Params +import Coln.FLIR.Value qualified as V +import Coln.SIR.Syntax qualified as S + +import Control.Monad (forM) +import Control.Monad.State + +import Data.Set qualified as Set + +newtype Els e = Els { unEls :: Trie (V.El e) } + +leaf :: V.El e -> Els e +leaf = Els . Leaf + +getLeaf :: Els e -> V.El e +getLeaf (Els (Leaf v)) = v +getLeaf _ = panic "tried to get leaf value of non-leaf" + +node :: Dict a -> [Els e] -> Els e +node d vs = Els $ Node $ Dict d.head (fromList $ (.unEls) <$> vs) + +proj :: Els e -> Name -> Els e +proj (Els (Node fields)) x = Els $ elemAt fields x +proj (Els (Leaf _)) _ = panic "tried to project from non-node" + +concatEls :: [Els e] -> [V.El e] +concatEls vs = toList $ go vs BwdNil + where + go [] vs' = vs' + go ((Els (Leaf v)):rest) vs' = go rest (vs' :> v) + go ((Els (Node d)):rest) vs' = go rest (go (Els <$> toList d.values) vs') + +newtype Props e = Props { apply :: Bwd (V.Prop e) -> Bwd (V.Prop e) } + +instance Semigroup (Props e) where + ps0 <> ps1 = Props (ps1.apply . ps0.apply) + +instance Monoid (Props e) where + mempty = Props id + +single :: V.Prop e -> Props e +single p = Props (:> p) + +data AuxilaryVars e = AuxilaryVars + { vars :: Bwd (V.ColName, V.ColType) + , props :: Bwd (V.Prop e) + , length :: Int + , usedRoots :: Set.Set Name + } + +newtype FlatM e a = FlatM {unFlatM :: State (AuxilaryVars e) a} + deriving (Functor, Applicative, Monad, MonadState (AuxilaryVars e)) + + +freshAt :: Path -> S.Shape -> FlatM e (Els e) +freshAt p = \case + S.Scalar t -> do + aux <- get + let i = aux.length + put $ aux { vars = (aux.vars :> (p, t)), length = (i + 1) } + pure $ leaf $ V.LocalVar $ FId i + S.Tuple fields -> do + fields' <- forM (toList fields) $ \(x, sh) -> freshAt (p :> x) sh + pure $ node fields fields' + +fresh :: Maybe Name -> S.Shape -> FlatM e (Els e) +fresh mx sh = do + x <- case mx of + Just x -> pure x + Nothing -> do + aux <- get + let x = freshNameFor aux.usedRoots + put $ aux {usedRoots = Set.insert x aux.usedRoots} + pure x + freshAt (BwdNil :> x) sh + +type Locals e = Bwd (Els e) + +class Flatten a (b :: Type -> Type) | a -> b where + flatten :: Locals e -> a -> FlatM e (b e) + +absName :: S.Abs a -> Maybe Name +absName (S.Abs mx _) = mx +absName (S.AbsConst _) = Nothing + +assert :: Props e -> FlatM e () +assert ps = modify (\aux -> aux { props = ps.apply aux.props }) + +app :: (Flatten a b) => Locals e -> S.Abs a -> Els e -> FlatM e (b e) +app l (S.Abs _ body) v = flatten (l :> v) body +app l (S.AbsConst body) _ = flatten l body + +instance Flatten (S.El Set) Els where + flatten l = \case + S.Var i -> pure $ elemAt l i + S.Single q -> do + v <- fresh (absName q.pred) q.shape + app l q.pred v >>= assert + pure v + S.Proj t x -> do + v <- flatten l t + pure $ proj v x + S.Cons fields -> do + fields' <- forM (toList fields) $ \(_, t) -> flatten l t + pure $ node fields fields' + S.Lit l -> pure $ leaf $ V.Lit l + +equate :: S.Shape -> Els e -> Els e -> Props e +equate (S.Scalar _) v0 v1 = single $ V.PEq (getLeaf v0) (getLeaf v1) +equate (S.Tuple fs) v0 v1 = + mconcat [ equate t (proj v0 x) (proj v1 x) | (x, t) <- toList fs ] + +instance Flatten S.Prop Props where + flatten l = \case + S.Atom tn mt args -> do + mv <- traverse (\t -> getLeaf <$> flatten l t) mt + argvs <- traverse (flatten l) args + pure $ single $ V.PAtom (V.Atom tn mv (Just <$> concatEls argvs)) + S.And ps -> mconcat <$> traverse (flatten l) (toList ps.values) + S.Eq sh t0 t1 -> do + v0 <- flatten l t0 + v1 <- flatten l t1 + pure $ equate sh v0 v1 + diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs new file mode 100644 index 00000000..5fb58d84 --- /dev/null +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -0,0 +1,63 @@ +module Coln.FLIR.Value where + +import Coln.Common +import Coln.Core.Params +import Coln.SIR.Syntax qualified as SIR + +import Data.Set qualified as Set +import GHC.Generics + +type ColName = Path + +type ColType = SIR.ScalarType + +data Materialization + = Recomputed + | Memoized + | Materialized + deriving (Show, Eq, Generic) + +data IndexMethod + = BTree + deriving (Show, Eq, Generic) + +data EntityVariant + = Table + | View Materialization + | Index IndexMethod [ColName] + deriving (Show, Eq, Generic) + +data Entity = Entity + { entityVariant :: EntityVariant + , columns :: [(ColName, ColType)] + , primaryKey :: Maybe (Set.Set ColName) + } + deriving (Show, Eq, Generic) + +-- The type parameter refers to the type of external references In the Realm IR, +-- this is Void, but in the FFI which constructs queries dynamically, this is +-- host-language expressions. +data El e + = Lit Literal + | LocalVar FId + | Extern e + deriving (Show, Eq, Generic) + +data Atom e = Atom + { entity :: TableName + , rowId :: Maybe (El e) + , values :: [Maybe (El e)] + } + +data Prop e + = PAtom (Atom e) + | PEq (El e) (El e) + +data RuleVariant = Enforced | Monitored + +data Rule = Rule + { ruleVariant :: RuleVariant + , vars :: [(ColName, ColType)] + , antecedents :: [Prop Void] + , consequents :: [Prop Void] + } diff --git a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs index 8f9e82e2..a9ebb883 100644 --- a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs +++ b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs @@ -1,8 +1,8 @@ module Coln.MIR.Evaluation where import Coln.Common -import Coln.MIR.Params import Coln.Core.Params +import Coln.MIR.Params import Coln.MIR.Syntax qualified as S import Coln.MIR.Value qualified as V @@ -31,9 +31,12 @@ instance Eval (S.Ty l) (V.Ty l) where S.LiftTy t -> V.LiftTy LSetTheory (eval vs t) S.U u -> V.U u S.EltOf tn args -> V.EltOf tn (eval vs <$> args) - S.Function ft -> V.Function $ - V.FunctionType SSetTheory (eval vs ft.dom) (evalAbs vs ft.cod) - S.Record rt -> V.Record $ - V.RecordType vs $ flip eval <$> rt.fieldTypes + S.Function ft -> + V.Function $ + V.FunctionType SSetTheory (eval vs ft.dom) (evalAbs vs ft.cod) + S.Record rt -> + V.Record $ + V.RecordType vs $ + flip eval <$> rt.fieldTypes S.BuiltinTy t -> V.BuiltinTy t S.Eq at lhs rhs -> V.Eq (eval vs at) (eval vs lhs) (eval vs rhs) diff --git a/packages/coln-compiler/src/Coln/MIR/Interpret.hs b/packages/coln-compiler/src/Coln/MIR/Interpret.hs index 94a7e785..e742ae96 100644 --- a/packages/coln-compiler/src/Coln/MIR/Interpret.hs +++ b/packages/coln-compiler/src/Coln/MIR/Interpret.hs @@ -3,10 +3,10 @@ module Coln.MIR.Interpret where -- Interpret Core syntax into MIR values import Coln.Common -import Coln.MIR.Value qualified as V -import Coln.MIR.Params -import Coln.Core.Syntax qualified as S import Coln.Core.Params +import Coln.Core.Syntax qualified as S +import Coln.MIR.Params +import Coln.MIR.Value qualified as V class Interp a (f :: MLevel -> Type) | a -> f where interp :: V.Globals -> V.Locals -> a -> Match SMLevel f diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs index 3206930b..2c308f34 100644 --- a/packages/coln-compiler/src/Coln/MIR/Layout.hs +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -9,14 +9,15 @@ import Data.String (fromString) import Data.Vector.Strict qualified as Vector import Coln.Common + -- import Coln.Core.Globals import Coln.Core.Params +import Coln.MIR.Memoed qualified as M import Coln.MIR.Params import Coln.MIR.Readback +import Coln.MIR.Realm import Coln.MIR.Syntax qualified as S import Coln.MIR.Value qualified as V -import Coln.MIR.Memoed qualified as M -import Coln.MIR.Realm -- Layout is the process of creating a realm from a theory, along with the -- universal model of that theory in the realm. @@ -44,15 +45,16 @@ emptyScope = Scope 0 BwdNil BwdNil BwdNil BwdNil Set.empty bind :: Scope -> Name -> V.Ty Set -> (V.El Set, Scope) bind sc x a = do let v = V.local (FId sc.len) - sc' = Scope - { len = sc.len + 1 - , names = sc.names :> x - , ctx = sc.ctx :> a - , bound = sc.bound :> v - , locals = sc.locals :> (Pair SSet v) - , usedNames = Set.insert x sc.usedNames - , realm = sc.realm - } + sc' = + Scope + { len = sc.len + 1 + , names = sc.names :> x + , ctx = sc.ctx :> a + , bound = sc.bound :> v + , locals = sc.locals :> (Pair SSet v) + , usedNames = Set.insert x sc.usedNames + , realm = sc.realm + } (v, sc') args :: Scope -> [M.El Set] diff --git a/packages/coln-compiler/src/Coln/MIR/Memoed.hs b/packages/coln-compiler/src/Coln/MIR/Memoed.hs index 9e104bdf..2957b23e 100644 --- a/packages/coln-compiler/src/Coln/MIR/Memoed.hs +++ b/packages/coln-compiler/src/Coln/MIR/Memoed.hs @@ -2,11 +2,11 @@ module Coln.MIR.Memoed where import Coln.Common import Coln.Core.Params +import Coln.MIR.Evaluation import Coln.MIR.Params +import Coln.MIR.Readback import Coln.MIR.Syntax qualified as S import Coln.MIR.Value qualified as V -import Coln.MIR.Readback -import Coln.MIR.Evaluation data Memoed (s :: MLevel -> Type) (v :: MLevel -> Type) (l :: MLevel) = M { stx :: s l diff --git a/packages/coln-compiler/src/Coln/MIR/Params.hs b/packages/coln-compiler/src/Coln/MIR/Params.hs index bd2dde45..e416b117 100644 --- a/packages/coln-compiler/src/Coln/MIR/Params.hs +++ b/packages/coln-compiler/src/Coln/MIR/Params.hs @@ -34,7 +34,7 @@ sDecodesInto = \case SSetU -> SSet SPropU -> SSet STheoryU -> STheory - + sCodesInto :: SUniverse l0 l1 -> SMLevel l1 sCodesInto = \case SSetU -> STheory @@ -69,4 +69,3 @@ withFunctionVariant :: FunctionVariantMLevel -> (forall l0 l1. SFunctionVariant withFunctionVariant fv f = case fv of SetTheory -> f SSetTheory TheoryTop -> f STheoryTop - diff --git a/packages/coln-compiler/src/Coln/MIR/Readback.hs b/packages/coln-compiler/src/Coln/MIR/Readback.hs index 335275c9..b19343a1 100644 --- a/packages/coln-compiler/src/Coln/MIR/Readback.hs +++ b/packages/coln-compiler/src/Coln/MIR/Readback.hs @@ -3,8 +3,8 @@ module Coln.MIR.Readback where import Coln.Common import Coln.Core.Params import Coln.MIR.Params -import Coln.MIR.Value qualified as V import Coln.MIR.Syntax qualified as S +import Coln.MIR.Value qualified as V type CtxLen = Int @@ -35,8 +35,8 @@ instance Readback (V.Ty Set) (S.Ty Set) where V.Eq at lhs rhs -> S.Eq (readb n at) (readb n lhs) (readb n rhs) V.Record rt -> do let go _ _ [] = [] - go n' vs ((x, k):rest) = - (x, readb n' (k vs)):(go (n' + 1) (vs :> Pair SSet (fresh n')) rest) + go n' vs ((x, k) : rest) = + (x, readb n' (k vs)) : (go (n' + 1) (vs :> Pair SSet (fresh n')) rest) let fieldTypes = fromList $ go n rt.capture (toList rt.fieldTypes) S.Record $ S.RecordType fieldTypes diff --git a/packages/coln-compiler/src/Coln/MIR/Realm.hs b/packages/coln-compiler/src/Coln/MIR/Realm.hs index 258e09af..29c3c1bb 100644 --- a/packages/coln-compiler/src/Coln/MIR/Realm.hs +++ b/packages/coln-compiler/src/Coln/MIR/Realm.hs @@ -2,9 +2,9 @@ module Coln.MIR.Realm where import Coln.Common import Coln.Core.Params +import Coln.MIR.Memoed qualified as M import Coln.MIR.Params import Coln.MIR.Value qualified as V -import Coln.MIR.Memoed qualified as M data Generator = Rel (SUniverse Set Theory) (Bwd Name) (Bwd (V.Ty Set)) diff --git a/packages/coln-compiler/src/Coln/MIR/Syntax.hs b/packages/coln-compiler/src/Coln/MIR/Syntax.hs index f595137d..b11fc066 100644 --- a/packages/coln-compiler/src/Coln/MIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/MIR/Syntax.hs @@ -1,8 +1,8 @@ module Coln.MIR.Syntax where import Coln.Common -import Coln.MIR.Params import Coln.Core.Params +import Coln.MIR.Params data Abs a = Abs Name a | AbsConst a @@ -16,14 +16,13 @@ data El :: MLevel -> Type where Proj :: El l -> Name -> El l Lit :: Literal -> El Set - data FunctionType = FunctionType { dom :: Ty Set , cod :: Abs (Ty Theory) } data RecordType l = RecordType - { fieldTypes :: Dict (Ty l) } + {fieldTypes :: Dict (Ty l)} data Ty :: MLevel -> Type where LiftTy :: Ty Set -> Ty Theory @@ -33,4 +32,3 @@ data Ty :: MLevel -> Type where Record :: RecordType l -> Ty l BuiltinTy :: BuiltinTy -> Ty Set Eq :: Ty Set -> El Set -> El Set -> Ty Set - diff --git a/packages/coln-compiler/src/Coln/MIR/Value.hs b/packages/coln-compiler/src/Coln/MIR/Value.hs index e2e01dc9..a72ed80d 100644 --- a/packages/coln-compiler/src/Coln/MIR/Value.hs +++ b/packages/coln-compiler/src/Coln/MIR/Value.hs @@ -46,7 +46,7 @@ app fv (Lam fv' _ clo) v = case (fv, fv') of app _ _ _ = panic "can only apply lambda" proj :: El l -> Name -> El l -proj (Neu n) x = Neu $ n { spine = n.spine :> x } +proj (Neu n) x = Neu $ n{spine = n.spine :> x} proj (Cons fields) x = elemAt fields x proj _ _ = panic "can only project from neutral or cons" @@ -71,7 +71,6 @@ instance LevelCoerce El where levelCoerce STop SSet (LiftEl LTheoryTop (LiftEl LSetTheory v)) = v levelCoerce _ _ _ = panic "cannot level coerce" - data FunctionType (l0 :: MLevel) (l1 :: MLevel) = FunctionType { variant :: SFunctionVariant l0 l1 , dom :: Ty l0 @@ -91,7 +90,7 @@ data Ty :: MLevel -> Type where Record :: RecordType l -> Ty l BuiltinTy :: BuiltinTy -> Ty Set Eq :: Ty Set -> El Set -> El Set -> Ty Set - + instance LevelCoerce Ty where levelCoerce SSet SSet v = v levelCoerce STheory STheory v = v diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs index 03ff8682..dd8395e5 100644 --- a/packages/coln-compiler/src/Coln/SIR/Cache.hs +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -5,8 +5,8 @@ import Coln.Core.Params import Coln.MIR.Params import Coln.MIR.Value qualified as V import Coln.SIR.Realm -import Coln.SIR.Syntax qualified as S import Coln.SIR.Separate +import Coln.SIR.Syntax qualified as S import Data.Set qualified as Set @@ -26,13 +26,14 @@ bind sc mx a = do Just x -> x Nothing -> freshNameFor sc.used let v = V.local (FId sc.len) - let sc' = sc - { len = sc.len + 1 - , ctx = sc.ctx :> q - , names = sc.names :> x - , bound = sc.bound :> v - , used = Set.insert x sc.used - } + let sc' = + sc + { len = sc.len + 1 + , ctx = sc.ctx :> q + , names = sc.names :> x + , bound = sc.bound :> v + , used = Set.insert x sc.used + } (x, v, sc') emptyNode :: Trie a @@ -49,9 +50,9 @@ cache p sc v = do let cols = toList (sc.ctx :> sa) let bound = toList (sc.bound :> V.local (FId sc.len)) let boundStx = separate (sc.len + 1) <$> bound - let ent = Entity View (toList sc.names) ((.shape) <$> cols) (Just [0..sc.len]) + let ent = Entity View (toList sc.names) ((.shape) <$> cols) (Just [0 .. sc.len]) let tn = TableName sc.realm p - let def = Definition cols tn boundStx + let def = Definition cols tn boundStx let prop = S.Atom tn Nothing boundStx let elt = S.Multi u $ S.Query sa.shape (S.Abs Nothing prop) (Leaf ent, Node (fromList [("definition", Leaf def)]), elt) @@ -65,7 +66,7 @@ cache p sc v = do (ents, defs, S.Lam (separate sc.len dom) (S.Abs (Just x) body)) V.Cons fields -> do let (ents, defs, fields') = - unzip3 [ cache (p :> x) sc field | (x, field) <- toList fields ] + unzip3 [cache (p :> x) sc field | (x, field) <- toList fields] ( Node (Dict fields.head (fromList ents)) , Node (Dict fields.head (fromList defs)) , S.Cons (Dict fields.head (fromList fields')) diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs index 5c414434..5bcce5ce 100644 --- a/packages/coln-compiler/src/Coln/SIR/Separate.hs +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -42,15 +42,15 @@ instance Separate (V.El Theory) (S.El Theory) where shapeOf :: V.Ty Set -> S.Shape shapeOf = \case - V.EltOf x _ -> S.RowId x + V.EltOf x _ -> S.Scalar $ S.RowId x V.Record rt -> do let go [] _ _ = [] - go ((x, k):rest) vs v = do + go ((x, k) : rest) vs v = do let v' = V.proj v x (x, shapeOf (k vs)) : (go rest (vs :> Pair SSet v') v) let v = V.local (FId 0) S.Tuple $ fromList $ go (toList rt.fieldTypes) rt.capture v - V.BuiltinTy t -> S.BuiltinTy t + V.BuiltinTy t -> S.Scalar $ S.BuiltinTy t V.Eq _ _ _ -> S.unitShape propAt :: CtxLen -> V.Ty Set -> V.El Set -> S.Prop @@ -59,7 +59,7 @@ propAt n = \case S.Atom x (Just (separate n v)) (separate n <$> args) V.Record rt -> \v -> do let go [] _ = [] - go ((x, k):rest) vs = do + go ((x, k) : rest) vs = do let v' = V.proj v x (x, propAt n (k vs) v') : (go rest (vs :> Pair SSet v')) S.And $ fromList $ go (toList rt.fieldTypes) rt.capture diff --git a/packages/coln-compiler/src/Coln/SIR/Syntax.hs b/packages/coln-compiler/src/Coln/SIR/Syntax.hs index 4c3a4a30..6363e575 100644 --- a/packages/coln-compiler/src/Coln/SIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/SIR/Syntax.hs @@ -4,6 +4,8 @@ import Coln.Common import Coln.Core.Params import Coln.MIR.Params +import GHC.Generics + data El :: MLevel -> Type where LiftEl :: El Set -> El Theory Var :: BId -> El Set @@ -19,10 +21,14 @@ data Prop | And (Dict Prop) | Eq Shape (El Set) (El Set) -data Shape +data ScalarType = RowId TableName - | Tuple (Dict Shape) | BuiltinTy BuiltinTy + deriving (Eq, Show, Generic) + +data Shape + = Tuple (Dict Shape) + | Scalar ScalarType unitShape :: Shape unitShape = Tuple (fromList []) @@ -38,4 +44,3 @@ data Query = Query { shape :: Shape , pred :: Abs Prop } - From 4ba3318100bac53963cfebe3749f8a1aa483b405 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Thu, 20 Aug 2026 16:56:43 +0100 Subject: [PATCH 05/42] flatten for realm components --- .../coln-compiler/src/Coln/FLIR/Flatten.hs | 72 ++++++++++++++++++- packages/coln-compiler/src/Coln/FLIR/Value.hs | 14 ++-- packages/coln-compiler/src/Coln/SIR/Realm.hs | 18 ++--- packages/coln-compiler/src/Coln/SIR/Syntax.hs | 5 ++ 4 files changed, 94 insertions(+), 15 deletions(-) diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index 744c79b7..aed7a6af 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -4,10 +4,11 @@ import Coln.Common import Coln.Core.Params import Coln.FLIR.Value qualified as V import Coln.SIR.Syntax qualified as S +import Coln.SIR.Realm qualified as S import Control.Monad (forM) import Control.Monad.State - +import Data.Vector.Strict qualified as Vec import Data.Set qualified as Set newtype Els e = Els { unEls :: Trie (V.El e) } @@ -41,12 +42,15 @@ instance Semigroup (Props e) where instance Monoid (Props e) where mempty = Props id +instance ToList (Props e) (V.Prop e) where + toList ps = toList (ps.apply BwdNil) + single :: V.Prop e -> Props e single p = Props (:> p) data AuxilaryVars e = AuxilaryVars { vars :: Bwd (V.ColName, V.ColType) - , props :: Bwd (V.Prop e) + , props :: Props e , length :: Int , usedRoots :: Set.Set Name } @@ -54,6 +58,10 @@ data AuxilaryVars e = AuxilaryVars newtype FlatM e a = FlatM {unFlatM :: State (AuxilaryVars e) a} deriving (Functor, Applicative, Monad, MonadState (AuxilaryVars e)) +runFlatM :: FlatM e a -> (a, [(V.ColName, V.ColType)], Props e) +runFlatM action = do + let (x, aux) = runState action.unFlatM (AuxilaryVars BwdNil mempty 0 Set.empty) + (x, toList aux.vars, aux.props) freshAt :: Path -> S.Shape -> FlatM e (Els e) freshAt p = \case @@ -87,7 +95,7 @@ absName (S.Abs mx _) = mx absName (S.AbsConst _) = Nothing assert :: Props e -> FlatM e () -assert ps = modify (\aux -> aux { props = ps.apply aux.props }) +assert ps = modify (\aux -> aux { props = aux.props <> ps }) app :: (Flatten a b) => Locals e -> S.Abs a -> Els e -> FlatM e (b e) app l (S.Abs _ body) v = flatten (l :> v) body @@ -125,3 +133,61 @@ instance Flatten S.Prop Props where v1 <- flatten l t1 pure $ equate sh v0 v1 +flattenColumn :: V.ColName -> S.Shape -> [(V.ColName, V.ColType)] +flattenColumn p = \case + S.Scalar t -> [(p, t)] + S.Tuple d -> concat [flattenColumn (p :> x) t | (x, t) <- toList d] + +flattenColumns :: [(Name, S.Shape)] -> [(V.ColName, V.ColType)] +flattenColumns = concat . fmap (\(x, sh) -> flattenColumn (BwdNil :> x) sh) + +flattenPrimaryKey :: [S.Shape] -> [Int] -> [Int] +flattenPrimaryKey shapes cols = do + let go n [] = [n] + go n (sh:rest) = do + let s = S.shapeSize sh + n : go (n + s) rest + let offsets = Vec.fromList $ go 0 shapes + concat [[(offsets Vec.! i)..(offsets Vec.! (i + 1)) - 1] | i <- cols] + +flattenEntity :: S.Entity -> V.Entity +flattenEntity e = V.Entity + { V.entityVariant = case e.entityVariant of + S.Table -> V.Table + S.View -> V.View V.Materialized + , V.columns = flattenColumns e.columns + , V.primaryKey = fmap (flattenPrimaryKey (snd <$> e.columns)) e.primaryKey + } + +bindTele :: Locals e -> [(Name, S.Query)] -> FlatM e (Locals e) +bindTele l [] = pure l +bindTele l ((x, a):rest) = do + v <- fresh (Just x) a.shape + app l a.pred v >>= assert + bindTele (l :> v) rest + +flattenRule :: S.Rule -> V.Rule +flattenRule r = do + let ((ante, cons), vars, ps) = runFlatM $ do + vs <- bindTele BwdNil r.inCtx + ante <- flatten vs r.antecedent + cons <- flatten vs r.consequent + pure (ante, cons) + V.Rule + { V.ruleVariant = r.ruleVariant + , V.vars = vars + , V.antecedents = toList (ps <> ante) + , V.consequents = toList cons + } + +flattenDefinition :: S.Definition -> V.Definition +flattenDefinition d = do + let (args, vars, ps) = runFlatM $ do + vs <- bindTele BwdNil d.inCtx + concatEls <$> traverse (flatten vs) d.args + V.Definition + { V.vars = vars + , V.antecedents = toList ps + , V.definand = d.definand + , V.args = args + } diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs index 5fb58d84..7389aadd 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Value.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -3,8 +3,8 @@ module Coln.FLIR.Value where import Coln.Common import Coln.Core.Params import Coln.SIR.Syntax qualified as SIR +import Coln.SIR.Realm qualified as SIR -import Data.Set qualified as Set import GHC.Generics type ColName = Path @@ -30,7 +30,7 @@ data EntityVariant data Entity = Entity { entityVariant :: EntityVariant , columns :: [(ColName, ColType)] - , primaryKey :: Maybe (Set.Set ColName) + , primaryKey :: Maybe [Int] } deriving (Show, Eq, Generic) @@ -53,11 +53,17 @@ data Prop e = PAtom (Atom e) | PEq (El e) (El e) -data RuleVariant = Enforced | Monitored data Rule = Rule - { ruleVariant :: RuleVariant + { ruleVariant :: SIR.RuleVariant , vars :: [(ColName, ColType)] , antecedents :: [Prop Void] , consequents :: [Prop Void] } + +data Definition = Definition + { vars :: [(ColName, ColType)] + , antecedents :: [Prop Void] + , definand :: TableName + , args :: [El Void] + } diff --git a/packages/coln-compiler/src/Coln/SIR/Realm.hs b/packages/coln-compiler/src/Coln/SIR/Realm.hs index 9fa4d60e..11da8f5c 100644 --- a/packages/coln-compiler/src/Coln/SIR/Realm.hs +++ b/packages/coln-compiler/src/Coln/SIR/Realm.hs @@ -4,25 +4,27 @@ import Coln.Common import Coln.Core.Params import Coln.SIR.Syntax -data EntityType +data EntityVariant = Table | View data Entity = Entity - { entityType :: EntityType - , columnNames :: [Name] - , columnShapes :: [Shape] + { entityVariant :: EntityVariant + , columns :: [(Name, Shape)] , primaryKey :: Maybe [Int] } data Definition = Definition - { inCtx :: [Query] + { inCtx :: [(Name, Query)] , definand :: TableName , args :: [El Set] } -data Law = Law - { inCtx :: [Query] +data RuleVariant = Enforced | Monitored + +data Rule = Rule + { ruleVariant :: RuleVariant + , inCtx :: [(Name, Query)] , antecedent :: Prop , consequent :: Prop } @@ -30,5 +32,5 @@ data Law = Law data Realm = Realm { entities :: Trie Entity , definitions :: Trie Definition - , laws :: Trie Law + , rules :: Trie Rule } diff --git a/packages/coln-compiler/src/Coln/SIR/Syntax.hs b/packages/coln-compiler/src/Coln/SIR/Syntax.hs index 6363e575..2774bfc3 100644 --- a/packages/coln-compiler/src/Coln/SIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/SIR/Syntax.hs @@ -30,6 +30,11 @@ data Shape = Tuple (Dict Shape) | Scalar ScalarType +shapeSize :: Shape -> Int +shapeSize = \case + Tuple ds -> sum $ shapeSize <$> toList ds.values + Scalar _ -> 1 + unitShape :: Shape unitShape = Tuple (fromList []) From 7f81b547e47a1e7c188b762e31f8938e8169f49f Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Thu, 20 Aug 2026 17:48:39 +0100 Subject: [PATCH 06/42] fixed elaborator, commented out ts gen --- packages/coln-compiler/coln-compiler.cabal | 1 + .../src/Coln/Backend/TypeScript/Assemble.hs | 52 +- .../src/Coln/Backend/TypeScript/Generate.hs | 487 +++++++++--------- .../src/Coln/Elaborator/Coercion.hs | 2 +- .../src/Coln/Elaborator/Environment.hs | 12 +- .../src/Coln/Elaborator/Rules/Function.hs | 6 +- .../src/Coln/Elaborator/Rules/Initial.hs | 8 +- .../src/Coln/Elaborator/Rules/Record.hs | 16 +- .../src/Coln/Elaborator/Rules/Universe.hs | 6 +- .../src/Coln/Elaborator/Rules/Variable.hs | 12 +- .../src/Coln/Frontend/Parser/Top.hs | 15 +- packages/coln-compiler/src/Coln/MIR/Layout.hs | 2 +- packages/coln-compiler/src/Coln/SIR/Cache.hs | 5 +- 13 files changed, 306 insertions(+), 318 deletions(-) diff --git a/packages/coln-compiler/coln-compiler.cabal b/packages/coln-compiler/coln-compiler.cabal index f5baa35b..038b5e26 100644 --- a/packages/coln-compiler/coln-compiler.cabal +++ b/packages/coln-compiler/coln-compiler.cabal @@ -57,6 +57,7 @@ library Coln.MIR.Value Coln.Report Coln.SIR.Cache + Coln.SIR.Realm Coln.SIR.Separate Coln.SIR.Syntax diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Assemble.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Assemble.hs index d82161e7..efb12c05 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Assemble.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Assemble.hs @@ -46,7 +46,7 @@ instance Assemble Ty where asm (ListTy a) = asm a <> "[]" instance Assemble Binding where - asm b = asm b . name <> ":" <+> asm b . ty + asm b = asm b.name <> ":" <+> asm b.ty instance Assemble BinOp where asm EqualsEquals = "==" @@ -85,62 +85,52 @@ instance Assemble Statement where instance Assemble Block where asm b = - let ret = case b . return of + let ret = case b.return of Just t -> ["return" <+> asm t <> ";"] Nothing -> [] - in hardBlocked $ (asm <$> b . statements) ++ ret + in hardBlocked $ (asm <$> b.statements) ++ ret instance Assemble Class where asm c = "class" - <+> asm c - . name - <> maybe mempty (\e -> " extends" <+> asm e) c . extends - <> maybe mempty (\i -> " implements" <+> asm i) c - . implements + <+> asm c.name + <> maybe mempty (\e -> " extends" <+> asm e) c.extends + <> maybe mempty (\i -> " implements" <+> asm i) c.implements <+> hardBlocked ( punctuate line - [ vsep [asm f <> ";" | f <- c . fields] - , asm c . constructor + [ vsep [asm f <> ";" | f <- c.fields] + , asm c.constructor ] ) instance Assemble Constructor where asm c = "constructor" - <> tupled (asm <$> c . args) - <+> asm c - . body + <> tupled (asm <$> c.args) + <+> asm c.body instance Assemble Interface where asm i = "interface" - <+> asm i - . name - <+> maybe mempty (\e -> "extends" <+> asm e <> " ") i - . extends - <> hardBlocked [asm f <> ";" | f <- i . fields] + <+> asm i.name + <+> maybe mempty (\e -> "extends" <+> asm e <> " ") i.extends + <> hardBlocked [asm f <> ";" | f <- i.fields] instance Assemble FunctionDef where asm f = "function" - <+> asm f - . name - <> tupled (asm <$> f . args) - <> maybe mempty (\ty -> ":" <+> asm ty) f - . ret - <+> asm f - . body + <+> asm f.name + <> tupled (asm <$> f.args) + <> maybe mempty (\ty -> ":" <+> asm ty) f.ret + <+> asm f.body instance Assemble TypeDef where asm td = "type" - <+> asm td - . name + <+> asm td.name <+> "=" - <+> asm td - . body + <+> asm td.body <> ";" instance (Assemble a) => Assemble (AccessControlled a) where @@ -169,7 +159,7 @@ instance Assemble Import where instance Assemble Module where asm m = vsep - [ vsep $ asm <$> m . imports + [ vsep $ asm <$> m.imports , "" - , vsep $ punctuate line $ asm <$> m . declarations + , vsep $ punctuate line $ asm <$> m.declarations ] diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs index 35e39753..337a0abb 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs @@ -4,247 +4,246 @@ module Coln.Backend.TypeScript.Generate where -import Control.Monad (forM_) -import Control.Monad.State -import Data.Aeson qualified as AE -import Data.Foldable (foldlM) -import Data.Foldable qualified as F -import Data.Map.Ordered qualified as OMap -import Data.Set (Set) -import Data.String (IsString (..)) -import Data.Text.Lazy qualified as TL -import Data.Text.Lazy.IO qualified as TLIO -import Prettyprinter -import Prettyprinter.Render.Text -import System.FilePath - -import Coln.Backend.Lower (lowerRealm) -import Coln.Backend.TypeScript.AST qualified as TS -import Coln.Backend.TypeScript.Assemble (asm) -import Coln.Backend.TypeScript.Params -import Coln.Common -import Coln.Core.Globals -import Coln.Core.Memoed -import Coln.Core.Params -import Coln.Core.Readback -import Coln.Core.Value qualified as V - -mangle :: Name -> TS.Id -mangle = TS.Id . mangleToDoc - -tyFromHead :: Access -> V.Head -> TS.Ty -tyFromHead access (V.GlobalVar x _) = - TS.TyConst (TS.QId [mangle x] (fromString (show access))) -tyFromHead access (V.LocalVar _) = TS.runtime $ ColnRef access -tyFromHead _ (V.Lookup _ _ _) = panic "table lookup cannot be used as a type" - -genTy :: Access -> CtxLen -> V.Ty N -> TS.Ty -genTy access n = \case - V.U (SetU; PropU) -> TS.runtime (ColnSet access) - V.Function ft -> do - let v = V.local (FId n) ft.dom - TS.Fun (TS.Binding (TS.Id "x") (TS.runtime Value)) (genTy access (n + 1) (V.appClo ft.cod v)) - V.EltOf _ _ -> TS.runtime $ ColnRef access - V.Decode n -> tyFromHead access n.head - V.BuiltinTy _ -> TS.runtime $ ColnRef access - _ -> error "not yet supported" - -genInterface :: Access -> CtxLen -> V.Ty D -> TS.Interface -genInterface access n = \case - V.Record rt -> do - let name = fromString $ show access - let extendsName = fromString . show <$> extends access - TS.Interface name extendsName (go n rt.capture (toList rt.fieldTypes)) - where - go _ _ [] = [] - go n' vs ((x, f) : rest) = do - let a = f vs - let v = V.local (FId n') a - let bnd = TS.Binding (mangle x) (genTy access n' a) - bnd : go (n' + 1) (V.LSnoc vs v) rest - -class TrackGlobals a where - trackGlobals :: a -> State (Set Name) () - --- instance TrackGlobals (f c) => TrackGlobals (S.Abs f c) where --- trackGlobals abs = trackGlobals (absBody abs) - --- instance TrackGlobals a => TrackGlobals (Name, a) where --- trackGlobals (_, t) = trackGlobals t - --- instance TrackGlobals (S.El c) where --- trackGlobals = \case --- S.LocalVar _ -> pure () --- S.GlobalVar x _ -> modify (Set.insert x) --- S.Code a -> trackGlobals a --- S.Lam dom body -> do --- trackGlobals dom --- trackGlobals body --- S.App t0 t1 -> do --- trackGlobals t0 --- trackGlobals t1 --- S.Cons ts -> mapM_ trackGlobals (toList ts) --- S.Proj t _ -> trackGlobals t --- S.Lit _ -> pure () --- S.Is t -> trackGlobals t --- S.Lookup _ _ -> pure () - --- instance TrackGlobals (S.Ty c) where --- trackGlobals = \case --- S.U _ -> pure () --- S.Decode t -> trackGlobals t --- S.Function ft -> do --- trackGlobals ft.dom --- trackGlobals ft.cod --- S.Record rt -> mapM_ trackGlobals (toList rt.fieldTypes) --- S.Eq et -> do --- trackGlobals et.lhs --- trackGlobals et.rhs --- S.BuiltinTy _ -> pure () --- S.IsTy a -> trackGlobals a --- S.EltOf _ _ -> pure () - -genTypeDef :: Access -> CtxLen -> V.Ty N -> TS.TypeDef -genTypeDef access n a = TS.TypeDef (fromShow access) (genTy access n a) - -genEntryModule :: [TS.Import] -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module -genEntryModule imports a ev = go 0 a ev - where - go :: CtxLen -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module - go n (V.U TheoryU) ev' = do - let definitions = for accessLevels $ \access -> - case V.ebind V.decode ev' of - V.Become a -> TS.DTypeDef $ genTypeDef access n a - V.Describe a -> TS.DInterface $ genInterface access n a - V.BecomeWith _ -> panic "can't lower becomewith yet" - Just $ TS.Module imports (TS.Exported <$> definitions) - go n (V.Function ft) ev' = do - let v = V.local (FId n) ft.dom - go (n + 1) (V.appClo ft.cod v) (V.ebind (flip V.app v) ev') - go _ _ _ = Nothing - -data TSCtxShape = TSCtxShape - { len :: CtxLen - , names :: Bwd TS.Id - } - -emptyTSCtxShape :: TSCtxShape -emptyTSCtxShape = TSCtxShape 0 BwdNil - -bind :: TSCtxShape -> TS.Id -> TSCtxShape -bind cs x = TSCtxShape{len = cs.len + 1, names = cs.names :> x} - -tableNameDoc :: TableName -> DDoc -tableNameDoc tn = concatWith (surround dot) (dpretty <$> (tn.realm : toList tn.path)) - -genTyVal :: Access -> TSCtxShape -> V.Ty N -> TS.El -genTyVal access cs = \case - V.EltOf x vs -> do - let params = TS.List $ genEl access cs <$> F.toList vs - let transactionArg = case access of - View -> [] - Transaction -> [TS.Var "transaction"] - let args = [TS.Var "store", TS.String (tableNameDoc x), params] ++ transactionArg - TS.New (TS.Const (TS.runtime (RowIdSet access))) args - _ -> panic "composite not yet supported" - -genHead :: Access -> TSCtxShape -> V.Head -> TS.El -genHead access cs = \case - V.LocalVar (FId i) -> TS.Var $ elemAt cs.names (BId (cs.len - i - 1)) - V.GlobalVar _ _ -> panic "global var neutral not yet supported" - V.Lookup tn vs _ -> do - let params = TS.List $ genEl access cs <$> F.toList vs - let transactionArg = case access of - View -> [] - Transaction -> [TS.Var "transaction"] - let args = [TS.Var "store", TS.String (tableNameDoc tn), params] ++ transactionArg - TS.New (TS.Const (TS.runtime (TableCellRef access))) args - -genSp :: TSCtxShape -> V.Spine -> TS.El -> TS.El -genSp _cs = \case - V.Id -> \t -> t - _ -> panic "unsupported spine operation" - -argName :: TSCtxShape -> V.Clo f c -> TS.Id -argName _ (V.Clo x _ _) = mangle x -argName _ (V.CloConst _) = panic "closures from the layout process should have argument names" - -genEl :: Access -> TSCtxShape -> V.El N -> TS.El -genEl access cs = \case - V.Neu n -> genSp cs n.spine $ genHead access cs n.head - V.InitNeu _ -> panic "can't lower init yet" - V.Code a -> genTyVal access cs a - V.Lam dom clo -> do - let v = V.local (FId cs.len) dom - let x = argName cs clo - TS.Lam - (TS.Binding x (TS.runtime Value)) - (TS.Block [] (Just (genEl access (bind cs x) (V.appClo clo v)))) - V.Cons fields -> TS.Object $ for (toList fields) $ \(x, v) -> - (mangle x, genEl access cs v) - V.Lit l -> TS.Lit l - -genRealmConstructor :: Access -> Realm -> TS.Constructor -genRealmConstructor access r = do - let args = case access of - View -> - [ TS.Binding "store" (TS.runtime StoreHandle) - ] - Transaction -> - [ TS.Binding "store" (TS.runtime StoreHandle) - , TS.Binding "transaction" (TS.runtime TransactionHandle) - ] - let superCall = case extends access of - Just _ -> [TS.Expr (TS.Call (TS.Var "super") [TS.Var "store"])] - Nothing -> [] - let body = - TS.Block - (superCall ++ [TS.Assign (TS.QId ["this"] "root") (genEl access emptyTSCtxShape r.root)]) - Nothing - TS.Constructor args body - -genRealmClass :: Access -> Realm -> TS.Class -genRealmClass access r = - TS.Class - (fromShow access) - Nothing - (fromShow <$> extends access) - [TS.Binding "root" (genTy access 0 r.rootType)] - (genRealmConstructor access r) - -genRealmModule :: [TS.Import] -> Realm -> TS.Module -genRealmModule imports r = do - let classes = for accessLevels $ \access -> TS.DClass $ genRealmClass access r - TS.Module imports (TS.Exported <$> classes) - -render :: DDoc -> TL.Text -render = renderLazy . layoutPretty defaultLayoutOptions - -writeModule :: FilePath -> Name -> TS.Module -> IO () -writeModule outdir x mod = do - let fn = outdir TS.idToString (mangle x) <> ".ts" - let content = render $ asm mod - TLIO.writeFile fn content - -runtimeImport :: TS.Import -runtimeImport = TS.ImportQualified "runtime" "@coln-project/runtime" - -forAccM :: (Monad m) => [b] -> a -> (a -> b -> m a) -> m a -forAccM bs init f = foldlM f init bs - -generate :: Globals -> FilePath -> IO () -generate ge outdir = do - typeImports <- forAccM (OMap.assocs ge.definitions) BwdNil $ \imports (x, e) -> do - let ev = e.body.val :: V.Evaluation V.El D - case genEntryModule (runtimeImport : toList imports) e.ty ev of - Just mod -> do - writeModule outdir x mod - pure (imports :> TS.ImportQualified (mangle x) ("./" <> mangleToDoc x <> ".ts")) - Nothing -> pure imports - let imports = runtimeImport : toList typeImports - forM_ (OMap.assocs ge.realms) $ \(x, r) -> do - let flat = lowerRealm x r - flip AE.encodeFile flat $ outdir mangleToString x <> ".json" - let schemaImport = TS.ImportSpecificExported "schema" $ "./" <> mangleToDoc x <> ".json" - let mod = genRealmModule (schemaImport : imports) r - writeModule outdir x mod +-- import Control.Monad (forM_) +-- import Control.Monad.State +-- import Data.Aeson qualified as AE +-- import Data.Foldable (foldlM) +-- import Data.Foldable qualified as F +-- import Data.Map.Ordered qualified as OMap +-- import Data.Set (Set) +-- import Data.String (IsString (..)) +-- import Data.Text.Lazy qualified as TL +-- import Data.Text.Lazy.IO qualified as TLIO +-- import Prettyprinter +-- import Prettyprinter.Render.Text +-- import System.FilePath + +-- import Coln.Backend.TypeScript.AST qualified as TS +-- import Coln.Backend.TypeScript.Assemble (asm) +-- import Coln.Backend.TypeScript.Params +-- import Coln.Common +-- import Coln.Core.Globals +-- import Coln.Core.Memoed +-- import Coln.Core.Params +-- import Coln.Core.Readback +-- import Coln.Core.Value qualified as V + +-- mangle :: Name -> TS.Id +-- mangle = TS.Id . mangleToDoc + +-- tyFromHead :: Access -> V.Head -> TS.Ty +-- tyFromHead access (V.GlobalVar x _) = +-- TS.TyConst (TS.QId [mangle x] (fromString (show access))) +-- tyFromHead access (V.LocalVar _) = TS.runtime $ ColnRef access +-- tyFromHead _ (V.Lookup _ _ _) = panic "table lookup cannot be used as a type" + +-- genTy :: Access -> CtxLen -> V.Ty N -> TS.Ty +-- genTy access n = \case +-- V.U (SetU; PropU) -> TS.runtime (ColnSet access) +-- V.Function ft -> do +-- let v = V.local (FId n) ft.dom +-- TS.Fun (TS.Binding (TS.Id "x") (TS.runtime Value)) (genTy access (n + 1) (V.appClo ft.cod v)) +-- V.EltOf _ _ -> TS.runtime $ ColnRef access +-- V.Decode n -> tyFromHead access n.head +-- V.BuiltinTy _ -> TS.runtime $ ColnRef access +-- _ -> error "not yet supported" + +-- genInterface :: Access -> CtxLen -> V.Ty D -> TS.Interface +-- genInterface access n = \case +-- V.Record rt -> do +-- let name = fromString $ show access +-- let extendsName = fromString . show <$> extends access +-- TS.Interface name extendsName (go n rt.capture (toList rt.fieldTypes)) +-- where +-- go _ _ [] = [] +-- go n' vs ((x, f) : rest) = do +-- let a = f vs +-- let v = V.local (FId n') a +-- let bnd = TS.Binding (mangle x) (genTy access n' a) +-- bnd : go (n' + 1) (V.LSnoc vs v) rest + +-- class TrackGlobals a where +-- trackGlobals :: a -> State (Set Name) () + +-- -- instance TrackGlobals (f c) => TrackGlobals (S.Abs f c) where +-- -- trackGlobals abs = trackGlobals (absBody abs) + +-- -- instance TrackGlobals a => TrackGlobals (Name, a) where +-- -- trackGlobals (_, t) = trackGlobals t + +-- -- instance TrackGlobals (S.El c) where +-- -- trackGlobals = \case +-- -- S.LocalVar _ -> pure () +-- -- S.GlobalVar x _ -> modify (Set.insert x) +-- -- S.Code a -> trackGlobals a +-- -- S.Lam dom body -> do +-- -- trackGlobals dom +-- -- trackGlobals body +-- -- S.App t0 t1 -> do +-- -- trackGlobals t0 +-- -- trackGlobals t1 +-- -- S.Cons ts -> mapM_ trackGlobals (toList ts) +-- -- S.Proj t _ -> trackGlobals t +-- -- S.Lit _ -> pure () +-- -- S.Is t -> trackGlobals t +-- -- S.Lookup _ _ -> pure () + +-- -- instance TrackGlobals (S.Ty c) where +-- -- trackGlobals = \case +-- -- S.U _ -> pure () +-- -- S.Decode t -> trackGlobals t +-- -- S.Function ft -> do +-- -- trackGlobals ft.dom +-- -- trackGlobals ft.cod +-- -- S.Record rt -> mapM_ trackGlobals (toList rt.fieldTypes) +-- -- S.Eq et -> do +-- -- trackGlobals et.lhs +-- -- trackGlobals et.rhs +-- -- S.BuiltinTy _ -> pure () +-- -- S.IsTy a -> trackGlobals a +-- -- S.EltOf _ _ -> pure () + +-- genTypeDef :: Access -> CtxLen -> V.Ty N -> TS.TypeDef +-- genTypeDef access n a = TS.TypeDef (fromShow access) (genTy access n a) + +-- genEntryModule :: [TS.Import] -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module +-- genEntryModule imports a ev = go 0 a ev +-- where +-- go :: CtxLen -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module +-- go n (V.U TheoryU) ev' = do +-- let definitions = for accessLevels $ \access -> +-- case V.ebind V.decode ev' of +-- V.Become a -> TS.DTypeDef $ genTypeDef access n a +-- V.Describe a -> TS.DInterface $ genInterface access n a +-- V.BecomeWith _ -> panic "can't lower becomewith yet" +-- Just $ TS.Module imports (TS.Exported <$> definitions) +-- go n (V.Function ft) ev' = do +-- let v = V.local (FId n) ft.dom +-- go (n + 1) (V.appClo ft.cod v) (V.ebind (flip V.app v) ev') +-- go _ _ _ = Nothing + +-- data TSCtxShape = TSCtxShape +-- { len :: CtxLen +-- , names :: Bwd TS.Id +-- } + +-- emptyTSCtxShape :: TSCtxShape +-- emptyTSCtxShape = TSCtxShape 0 BwdNil + +-- bind :: TSCtxShape -> TS.Id -> TSCtxShape +-- bind cs x = TSCtxShape{len = cs.len + 1, names = cs.names :> x} + +-- tableNameDoc :: TableName -> DDoc +-- tableNameDoc tn = concatWith (surround dot) (dpretty <$> (tn.realm : toList tn.path)) + +-- genTyVal :: Access -> TSCtxShape -> V.Ty N -> TS.El +-- genTyVal access cs = \case +-- V.EltOf x vs -> do +-- let params = TS.List $ genEl access cs <$> F.toList vs +-- let transactionArg = case access of +-- View -> [] +-- Transaction -> [TS.Var "transaction"] +-- let args = [TS.Var "store", TS.String (tableNameDoc x), params] ++ transactionArg +-- TS.New (TS.Const (TS.runtime (RowIdSet access))) args +-- _ -> panic "composite not yet supported" + +-- genHead :: Access -> TSCtxShape -> V.Head -> TS.El +-- genHead access cs = \case +-- V.LocalVar (FId i) -> TS.Var $ elemAt cs.names (BId (cs.len - i - 1)) +-- V.GlobalVar _ _ -> panic "global var neutral not yet supported" +-- V.Lookup tn vs _ -> do +-- let params = TS.List $ genEl access cs <$> F.toList vs +-- let transactionArg = case access of +-- View -> [] +-- Transaction -> [TS.Var "transaction"] +-- let args = [TS.Var "store", TS.String (tableNameDoc tn), params] ++ transactionArg +-- TS.New (TS.Const (TS.runtime (TableCellRef access))) args + +-- genSp :: TSCtxShape -> V.Spine -> TS.El -> TS.El +-- genSp _cs = \case +-- V.Id -> \t -> t +-- _ -> panic "unsupported spine operation" + +-- argName :: TSCtxShape -> V.Clo f c -> TS.Id +-- argName _ (V.Clo x _ _) = mangle x +-- argName _ (V.CloConst _) = panic "closures from the layout process should have argument names" + +-- genEl :: Access -> TSCtxShape -> V.El N -> TS.El +-- genEl access cs = \case +-- V.Neu n -> genSp cs n.spine $ genHead access cs n.head +-- V.InitNeu _ -> panic "can't lower init yet" +-- V.Code a -> genTyVal access cs a +-- V.Lam dom clo -> do +-- let v = V.local (FId cs.len) dom +-- let x = argName cs clo +-- TS.Lam +-- (TS.Binding x (TS.runtime Value)) +-- (TS.Block [] (Just (genEl access (bind cs x) (V.appClo clo v)))) +-- V.Cons fields -> TS.Object $ for (toList fields) $ \(x, v) -> +-- (mangle x, genEl access cs v) +-- V.Lit l -> TS.Lit l + +-- genRealmConstructor :: Access -> Realm -> TS.Constructor +-- genRealmConstructor access r = do +-- let args = case access of +-- View -> +-- [ TS.Binding "store" (TS.runtime StoreHandle) +-- ] +-- Transaction -> +-- [ TS.Binding "store" (TS.runtime StoreHandle) +-- , TS.Binding "transaction" (TS.runtime TransactionHandle) +-- ] +-- let superCall = case extends access of +-- Just _ -> [TS.Expr (TS.Call (TS.Var "super") [TS.Var "store"])] +-- Nothing -> [] +-- let body = +-- TS.Block +-- (superCall ++ [TS.Assign (TS.QId ["this"] "root") (genEl access emptyTSCtxShape r.root)]) +-- Nothing +-- TS.Constructor args body + +-- genRealmClass :: Access -> Realm -> TS.Class +-- genRealmClass access r = +-- TS.Class +-- (fromShow access) +-- Nothing +-- (fromShow <$> extends access) +-- [TS.Binding "root" (genTy access 0 r.rootType)] +-- (genRealmConstructor access r) + +-- genRealmModule :: [TS.Import] -> Realm -> TS.Module +-- genRealmModule imports r = do +-- let classes = for accessLevels $ \access -> TS.DClass $ genRealmClass access r +-- TS.Module imports (TS.Exported <$> classes) + +-- render :: DDoc -> TL.Text +-- render = renderLazy . layoutPretty defaultLayoutOptions + +-- writeModule :: FilePath -> Name -> TS.Module -> IO () +-- writeModule outdir x mod = do +-- let fn = outdir TS.idToString (mangle x) <> ".ts" +-- let content = render $ asm mod +-- TLIO.writeFile fn content + +-- runtimeImport :: TS.Import +-- runtimeImport = TS.ImportQualified "runtime" "@coln-project/runtime" + +-- forAccM :: (Monad m) => [b] -> a -> (a -> b -> m a) -> m a +-- forAccM bs init f = foldlM f init bs + +-- generate :: Globals -> FilePath -> IO () +-- generate ge outdir = do +-- typeImports <- forAccM (OMap.assocs ge.definitions) BwdNil $ \imports (x, e) -> do +-- let ev = e.body.val :: V.Evaluation V.El D +-- case genEntryModule (runtimeImport : toList imports) e.ty ev of +-- Just mod -> do +-- writeModule outdir x mod +-- pure (imports :> TS.ImportQualified (mangle x) ("./" <> mangleToDoc x <> ".ts")) +-- Nothing -> pure imports +-- let imports = runtimeImport : toList typeImports +-- forM_ (OMap.assocs ge.realms) $ \(x, r) -> do +-- let flat = lowerRealm x r +-- flip AE.encodeFile flat $ outdir mangleToString x <> ".json" +-- let schemaImport = TS.ImportSpecificExported "schema" $ "./" <> mangleToDoc x <> ".json" +-- let mod = genRealmModule (schemaImport : imports) r +-- writeModule outdir x mod diff --git a/packages/coln-compiler/src/Coln/Elaborator/Coercion.hs b/packages/coln-compiler/src/Coln/Elaborator/Coercion.hs index 12a74a6b..48b33ce5 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Coercion.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Coercion.hs @@ -24,7 +24,7 @@ intoSyn _ sp (FromTyp t) = Syn $ \e -> do Nothing -> do let msg = "type" <+> prtIn e raw <+> "too large to fit in a universe" failWith e.diagEnv sp TypeTooLarge msg - Just u -> pure (V.U u, M.code raw) + Just u -> pure (V.U u, M.code u raw) intoSyn _ _ (FromSyn s) = s intoSyn use sp (FromChk nd _) = Syn $ \e -> do let msg = "Type annotation required when using a" <+> nd <+> "as" <+> use diff --git a/packages/coln-compiler/src/Coln/Elaborator/Environment.hs b/packages/coln-compiler/src/Coln/Elaborator/Environment.hs index a7848318..dfa52121 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Environment.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Environment.hs @@ -76,13 +76,13 @@ data Target :: Case -> Type where TargetAnonymous :: Target N TargetNamed :: V.BareNeutral -> Target D -projTarget :: Target c -> Name -> Target c -projTarget TargetAnonymous _ = TargetAnonymous -projTarget (TargetNamed n) x = TargetNamed n{BN.spine = V.Proj n.spine x} +projTarget :: Level -> Target c -> Name -> Target c +projTarget _ TargetAnonymous _ = TargetAnonymous +projTarget l (TargetNamed n) x = TargetNamed n{BN.spine = V.Proj l n.spine x} -appTarget :: Target c -> V.El N -> Target c -appTarget TargetAnonymous _ = TargetAnonymous -appTarget (TargetNamed n) x = TargetNamed n{BN.spine = V.App n.spine x} +appTarget :: FunctionVariant -> Target c -> V.El N -> Target c +appTarget _ TargetAnonymous _ = TargetAnonymous +appTarget fv (TargetNamed n) v = TargetNamed n{BN.spine = V.App fv n.spine v} reflectTarget :: Target c -> V.Ty N -> V.Evaluation V.El c -> V.El N reflectTarget TargetAnonymous _ v = v diff --git a/packages/coln-compiler/src/Coln/Elaborator/Rules/Function.hs b/packages/coln-compiler/src/Coln/Elaborator/Rules/Function.hs index ca3ed349..b73f6e5c 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Rules/Function.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Rules/Function.hs @@ -42,9 +42,9 @@ intro sp x body = Chk \e a -> V.LikeFunction ft -> do ebody <- withBound x ft.dom ft.variant.domainMode e.scope $ \v scope' -> body.elab - (e{scope = scope', target = appTarget e.target v}) + (e{scope = scope', target = appTarget ft.variant e.target v}) (V.appClo ft.cod v) - pure $ lam e.scope.locals (fromVTy e.scope.len a) (S.Abs x ebody) + pure $ lam ft.variant e.scope.locals (fromVTy e.scope.len a) (S.Abs x ebody) _ -> do let msg = "tried to check a lambda expression at a non-function type" failWith e.diagEnv sp CheckLambdaAtNonFunctionType msg @@ -55,7 +55,7 @@ elim sp callee arg = Syn $ \e -> do case V.behavior ty of V.LikeFunction ft -> do earg <- arg.elab (e{scope = shiftToMode ft.variant.domainMode e.scope}) ft.dom - pure (V.appClo ft.cod earg.val, app ecallee earg) + pure (V.appClo ft.cod earg.val, app ft.variant ecallee earg) _ -> do let msg = "tried to apply a value that was not of a function type" failWith e.diagEnv sp ApplicationOfNonFunction msg diff --git a/packages/coln-compiler/src/Coln/Elaborator/Rules/Initial.hs b/packages/coln-compiler/src/Coln/Elaborator/Rules/Initial.hs index 9a961988..b2fc2919 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Rules/Initial.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Rules/Initial.hs @@ -13,10 +13,10 @@ import Coln.Elaborator.Judgment create :: Span -> Typ N -> Syn D create sp t = Syn \e -> do - case e . scope . mode of + case e.scope.mode of Inductive -> pure () Conjunctive -> do let msg = "cannot create initial model in conjunctive mode" - failWith e . diagEnv sp InitInConjunctive msg - a <- t . elab (e{scope = lock e . scope, target = TargetAnonymous}) - pure (a . val, init a) + failWith e.diagEnv sp InitInConjunctive msg + a <- t.elab (e{scope = lock e.scope, target = TargetAnonymous}) + pure (a.val, init a) diff --git a/packages/coln-compiler/src/Coln/Elaborator/Rules/Record.hs b/packages/coln-compiler/src/Coln/Elaborator/Rules/Record.hs index b51501b8..bc2b7e69 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Rules/Record.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Rules/Record.hs @@ -39,15 +39,15 @@ data FieldSetting c = FieldSetting intro :: (V.HasEvaluation c) => Span -> [FieldSetting c] -> Chk c intro @c sp fieldSettings = Chk \e a -> do - let go :: V.Locals -> [(FieldSetting c, (Name, V.Locals -> V.Ty N))] -> IO [(Name, El c)] - go _ [] = pure [] - go vs ((fs, (x, fieldTyC)) : rest) + let go :: Level -> V.Locals -> [(FieldSetting c, (Name, V.Locals -> V.Ty N))] -> IO [(Name, El c)] + go lvl _ [] = pure [] + go lvl vs ((fs, (x, fieldTyC)) : rest) | fs.name == x = do let fieldTy = fieldTyC vs - let target' = projTarget e.target x + let target' = projTarget lvl e.target x m <- fs.body.elab (e{target = target'}) fieldTy let v = reflectTarget target' fieldTy m.val - fields <- go (V.LSnoc vs v) rest + fields <- go lvl (V.LSnoc vs v) rest pure ((x, m) : fields) | otherwise = do let msg = "expected record field" <+> dpretty x <+> "got: " <+> dpretty fs.name @@ -59,8 +59,8 @@ intro @c sp fieldSettings = Chk \e a -> do unless (expectedLength == givenLength) $ do let msg = "expected" <+> pretty expectedLength <+> "fields, got: " <+> pretty givenLength failWith e.diagEnv sp WrongNumberOfRecordFields msg - fields <- go rt.capture (zip fieldSettings (toList rt.fieldTypes)) - pure $ cons (fromList fields) + fields <- go rt.level rt.capture (zip fieldSettings (toList rt.fieldTypes)) + pure $ cons rt.level (fromList fields) _ -> do let msg = "tried to check a record expression at a non-record type" failWith e.diagEnv sp CheckRecordAtNonRecordType msg @@ -73,7 +73,7 @@ elim sp projectee x = Syn \e -> do unless (contains rt.fieldTypes x) $ do let msg = "no such field" <+> dpretty x <+> "in type" <+> prtIn e ty failWith e.diagEnv sp NoSuchField msg - pure (V.projTy ty eprojectee.val x, proj eprojectee x) + pure (V.projTy ty eprojectee.val x, proj rt.level eprojectee x) _ -> do let msg = "tried to project from a value that was not of a record type" failWith e.diagEnv sp ProjectionOfNonRecord msg diff --git a/packages/coln-compiler/src/Coln/Elaborator/Rules/Universe.hs b/packages/coln-compiler/src/Coln/Elaborator/Rules/Universe.hs index 37d02cf9..b60ac10f 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Rules/Universe.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Rules/Universe.hs @@ -18,7 +18,7 @@ intro sp t = Chk $ \e ty -> do case V.behavior ty of V.LikeU u -> do case leq (levelOf raw) (decodesInto u) of - True -> pure $ code raw + True -> pure $ code u raw False -> do let msg = "type" <+> prtIn e raw <+> "too large for universe" <+> pretty u failWith e.diagEnv sp TypeTooLarge msg @@ -29,13 +29,13 @@ intro sp t = Chk $ \e ty -> do elim :: Universe -> Chk N -> Typ N elim u c = Typ \e -> do el <- c.elab e $ V.U u - pure $ decode el + pure $ decode u el elimSyn :: Span -> Syn N -> Typ N elimSyn sp s = Typ \e -> do (a, el) <- s.elab e case V.behavior a of - V.LikeU _ -> pure $ decode el + V.LikeU u -> pure $ decode u el _ -> do let msg = "expected element of universe type" failWith e.diagEnv sp TypeAtNonUniverse msg diff --git a/packages/coln-compiler/src/Coln/Elaborator/Rules/Variable.hs b/packages/coln-compiler/src/Coln/Elaborator/Rules/Variable.hs index 4d55abd4..b1051f9c 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Rules/Variable.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Rules/Variable.hs @@ -15,15 +15,15 @@ import Coln.Elaborator.Judgment find :: Span -> Name -> Syn N find sp x = Syn \e -> do - (ty, tm, m) <- case lookup e . scope x of + (ty, tm, m) <- case lookup e.scope x of Just (i, v, ty, m) -> pure (ty, localVar i v, m) - Nothing -> case lookup e . globals x of - Just ge -> pure (ge . ty, globalVar x ge . reflected, ge . mode) + Nothing -> case lookup e.globals x of + Just ge -> pure (ge.ty, globalVar x ge.reflected, ge.mode) Nothing -> do let msg = "no such variable" <+> dpretty x <+> "in scope" - failWith e . diagEnv sp VariableNotInScope msg - case (m, e . scope . mode) of + failWith e.diagEnv sp VariableNotInScope msg + case (m, e.scope.mode) of (Inductive, Conjunctive) -> do let msg = "cannot use inductively bound variable in a conjunctive context" - failWith e . diagEnv sp InductiveInConjunctive msg + failWith e.diagEnv sp InductiveInConjunctive msg _ -> pure (ty, tm) diff --git a/packages/coln-compiler/src/Coln/Frontend/Parser/Top.hs b/packages/coln-compiler/src/Coln/Frontend/Parser/Top.hs index 44777bc4..59112868 100644 --- a/packages/coln-compiler/src/Coln/Frontend/Parser/Top.hs +++ b/packages/coln-compiler/src/Coln/Frontend/Parser/Top.hs @@ -8,7 +8,7 @@ import Control.Exception (try) import Data.Foldable import Data.Functor.Contravariant (contramap) import Data.List.NonEmpty (NonEmpty (..)) -import Data.Map.Ordered (OMap) + import Data.Map.Ordered qualified as OMap import FNotation (Ntn) import FNotation qualified as N @@ -16,7 +16,6 @@ import Prettyprinter import Coln.Common import Coln.Core -import Coln.Core.Layout import Coln.Core.Memoed qualified as M import Coln.Core.Value qualified as V import Coln.Diagnostics @@ -117,10 +116,8 @@ realm e g head def_ns = do (x, theory_n) <- realmHead (contramap ParserCode e) head theory_typ <- typ (contramap ParserCode e) theory_n theory <- theory_typ.elab (emptyElabEnv (contramap ElaboratorCode e) g Inductive) - let (gt, root) = layoutTop x theory.val - defs <- realmDecls e g theory.val root.val def_ns - let (gts, defs') = layoutDecls defs - pure (x, Realm gt root.val theory.val defs) + defs <- realmDecls e g theory.val def_ns + pure (x, Realm theory defs) elabRealmDefinition :: ElabEnv N -> Mode -> (Typ N, Chk D) -> IO (Definition Local) elabRealmDefinition e m (ty, tm) = do @@ -140,10 +137,10 @@ realmDecl de e (N.MDecl ms "def" n sp) = do pure (x, d) realmDecl de _ n = unexpectedNotation (contramap ParserCode de) n "realm declaration" -realmDecls :: DiagnosticEnv ColnCode -> Globals -> V.Ty N -> V.El N -> [Ntn] -> IO (OMap Name (Definition Local)) -realmDecls de g theory root ns = do +realmDecls :: DiagnosticEnv ColnCode -> Globals -> V.Ty N -> [Ntn] -> IO (OMap Name (Definition Local)) +realmDecls de g theory ns = do let e0 = emptyElabEnv (contramap ElaboratorCode de) g Conjunctive - let e = e0{scope = let_ "root" root theory Conjunctive e0.scope} + let e = e0{scope = bind "root" theory Conjunctive e0.scope} let addDecl (e', ds) n = do (x, d) <- realmDecl de e' n pure diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs index 2c308f34..87035412 100644 --- a/packages/coln-compiler/src/Coln/MIR/Layout.hs +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -73,7 +73,7 @@ layout p sc = \case let x = argName sc.usedNames ft.cod let (v, sc') = bind sc x ft.dom let (gt, m) = layout p sc' (V.appClo ft.cod v) - (gt, M.lam sc.locals (S.Abs x m.stx)) + (gt, M.lam sc.locals (M.fromV sc.len ft.dom) (S.Abs x m.stx)) V.Record rt -> do let go _ [] = ([], []) go l ((x, a) : rest) = do diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs index dd8395e5..595f6a4d 100644 --- a/packages/coln-compiler/src/Coln/SIR/Cache.hs +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -50,9 +50,10 @@ cache p sc v = do let cols = toList (sc.ctx :> sa) let bound = toList (sc.bound :> V.local (FId sc.len)) let boundStx = separate (sc.len + 1) <$> bound - let ent = Entity View (toList sc.names) ((.shape) <$> cols) (Just [0 .. sc.len]) + let xs = toList sc.names + let ent = Entity View (zip xs ((.shape) <$> cols)) (Just [0 .. sc.len]) let tn = TableName sc.realm p - let def = Definition cols tn boundStx + let def = Definition (zip xs cols) tn boundStx let prop = S.Atom tn Nothing boundStx let elt = S.Multi u $ S.Query sa.shape (S.Abs Nothing prop) (Leaf ent, Node (fromList [("definition", Leaf def)]), elt) From 269065d37f2d4d3c4fef9cdfdbbc32f6846b113f Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Thu, 20 Aug 2026 17:49:17 +0100 Subject: [PATCH 07/42] formatting --- packages/coln-compiler/src/Coln/Common.hs | 1 - .../coln-compiler/src/Coln/FLIR/Flatten.hs | 47 ++++++++++--------- packages/coln-compiler/src/Coln/FLIR/Value.hs | 3 +- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index daaa4502..96af406d 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -99,7 +99,6 @@ instance (Ord a) => ElemAt (OMap a b) a b where elemAt m k = case OMap.lookup k m of Just v -> v Nothing -> panic "no such key found in map" - class Lookup a i b | a -> i b where lookup :: a -> i -> Maybe b diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index aed7a6af..a05e1265 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -3,15 +3,15 @@ module Coln.FLIR.Flatten where import Coln.Common import Coln.Core.Params import Coln.FLIR.Value qualified as V -import Coln.SIR.Syntax qualified as S import Coln.SIR.Realm qualified as S +import Coln.SIR.Syntax qualified as S import Control.Monad (forM) import Control.Monad.State -import Data.Vector.Strict qualified as Vec import Data.Set qualified as Set +import Data.Vector.Strict qualified as Vec -newtype Els e = Els { unEls :: Trie (V.El e) } +newtype Els e = Els {unEls :: Trie (V.El e)} leaf :: V.El e -> Els e leaf = Els . Leaf @@ -29,12 +29,12 @@ proj (Els (Leaf _)) _ = panic "tried to project from non-node" concatEls :: [Els e] -> [V.El e] concatEls vs = toList $ go vs BwdNil - where - go [] vs' = vs' - go ((Els (Leaf v)):rest) vs' = go rest (vs' :> v) - go ((Els (Node d)):rest) vs' = go rest (go (Els <$> toList d.values) vs') + where + go [] vs' = vs' + go ((Els (Leaf v)) : rest) vs' = go rest (vs' :> v) + go ((Els (Node d)) : rest) vs' = go rest (go (Els <$> toList d.values) vs') -newtype Props e = Props { apply :: Bwd (V.Prop e) -> Bwd (V.Prop e) } +newtype Props e = Props {apply :: Bwd (V.Prop e) -> Bwd (V.Prop e)} instance Semigroup (Props e) where ps0 <> ps1 = Props (ps1.apply . ps0.apply) @@ -68,7 +68,7 @@ freshAt p = \case S.Scalar t -> do aux <- get let i = aux.length - put $ aux { vars = (aux.vars :> (p, t)), length = (i + 1) } + put $ aux{vars = (aux.vars :> (p, t)), length = (i + 1)} pure $ leaf $ V.LocalVar $ FId i S.Tuple fields -> do fields' <- forM (toList fields) $ \(x, sh) -> freshAt (p :> x) sh @@ -81,10 +81,10 @@ fresh mx sh = do Nothing -> do aux <- get let x = freshNameFor aux.usedRoots - put $ aux {usedRoots = Set.insert x aux.usedRoots} + put $ aux{usedRoots = Set.insert x aux.usedRoots} pure x freshAt (BwdNil :> x) sh - + type Locals e = Bwd (Els e) class Flatten a (b :: Type -> Type) | a -> b where @@ -95,7 +95,7 @@ absName (S.Abs mx _) = mx absName (S.AbsConst _) = Nothing assert :: Props e -> FlatM e () -assert ps = modify (\aux -> aux { props = aux.props <> ps }) +assert ps = modify (\aux -> aux{props = aux.props <> ps}) app :: (Flatten a b) => Locals e -> S.Abs a -> Els e -> FlatM e (b e) app l (S.Abs _ body) v = flatten (l :> v) body @@ -119,7 +119,7 @@ instance Flatten (S.El Set) Els where equate :: S.Shape -> Els e -> Els e -> Props e equate (S.Scalar _) v0 v1 = single $ V.PEq (getLeaf v0) (getLeaf v1) equate (S.Tuple fs) v0 v1 = - mconcat [ equate t (proj v0 x) (proj v1 x) | (x, t) <- toList fs ] + mconcat [equate t (proj v0 x) (proj v1 x) | (x, t) <- toList fs] instance Flatten S.Prop Props where flatten l = \case @@ -144,24 +144,25 @@ flattenColumns = concat . fmap (\(x, sh) -> flattenColumn (BwdNil :> x) sh) flattenPrimaryKey :: [S.Shape] -> [Int] -> [Int] flattenPrimaryKey shapes cols = do let go n [] = [n] - go n (sh:rest) = do + go n (sh : rest) = do let s = S.shapeSize sh n : go (n + s) rest let offsets = Vec.fromList $ go 0 shapes - concat [[(offsets Vec.! i)..(offsets Vec.! (i + 1)) - 1] | i <- cols] + concat [[(offsets Vec.! i) .. (offsets Vec.! (i + 1)) - 1] | i <- cols] flattenEntity :: S.Entity -> V.Entity -flattenEntity e = V.Entity - { V.entityVariant = case e.entityVariant of - S.Table -> V.Table - S.View -> V.View V.Materialized - , V.columns = flattenColumns e.columns - , V.primaryKey = fmap (flattenPrimaryKey (snd <$> e.columns)) e.primaryKey - } +flattenEntity e = + V.Entity + { V.entityVariant = case e.entityVariant of + S.Table -> V.Table + S.View -> V.View V.Materialized + , V.columns = flattenColumns e.columns + , V.primaryKey = fmap (flattenPrimaryKey (snd <$> e.columns)) e.primaryKey + } bindTele :: Locals e -> [(Name, S.Query)] -> FlatM e (Locals e) bindTele l [] = pure l -bindTele l ((x, a):rest) = do +bindTele l ((x, a) : rest) = do v <- fresh (Just x) a.shape app l a.pred v >>= assert bindTele (l :> v) rest diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs index 7389aadd..0731472e 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Value.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -2,8 +2,8 @@ module Coln.FLIR.Value where import Coln.Common import Coln.Core.Params -import Coln.SIR.Syntax qualified as SIR import Coln.SIR.Realm qualified as SIR +import Coln.SIR.Syntax qualified as SIR import GHC.Generics @@ -53,7 +53,6 @@ data Prop e = PAtom (Atom e) | PEq (El e) (El e) - data Rule = Rule { ruleVariant :: SIR.RuleVariant , vars :: [(ColName, ColType)] From 3027b5f9f9e9fec217e80b98df42663964ce367c Mon Sep 17 00:00:00 2001 From: mvr Date: Thu, 20 Aug 2026 19:32:20 +0100 Subject: [PATCH 08/42] separate for Generators, plumb HLevel down to SIR --- .../coln-compiler/src/Coln/Core/Params.hs | 3 + .../coln-compiler/src/Coln/FLIR/Flatten.hs | 48 +++++++++------- .../coln-compiler/src/Coln/MIR/Evaluation.hs | 7 ++- .../coln-compiler/src/Coln/MIR/Interpret.hs | 4 +- packages/coln-compiler/src/Coln/MIR/Layout.hs | 6 +- packages/coln-compiler/src/Coln/MIR/Memoed.hs | 4 +- packages/coln-compiler/src/Coln/MIR/Params.hs | 25 +++++++-- .../coln-compiler/src/Coln/MIR/Readback.hs | 5 +- packages/coln-compiler/src/Coln/MIR/Syntax.hs | 10 +++- packages/coln-compiler/src/Coln/MIR/Value.hs | 19 +++++-- packages/coln-compiler/src/Coln/SIR/Cache.hs | 2 +- packages/coln-compiler/src/Coln/SIR/Realm.hs | 3 + .../coln-compiler/src/Coln/SIR/Separate.hs | 55 ++++++++++++++++--- packages/coln-compiler/src/Coln/SIR/Syntax.hs | 8 +-- 14 files changed, 142 insertions(+), 57 deletions(-) diff --git a/packages/coln-compiler/src/Coln/Core/Params.hs b/packages/coln-compiler/src/Coln/Core/Params.hs index d6b451c6..87c500d5 100644 --- a/packages/coln-compiler/src/Coln/Core/Params.hs +++ b/packages/coln-compiler/src/Coln/Core/Params.hs @@ -51,6 +51,9 @@ equalityHLevelOf = \case HSet -> HProp HTop -> HTop +class HLevelOf a where + hlevelOf :: a -> HLevel + data Level = Level { mlevel :: MLevel , hlevel :: HLevel diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index a05e1265..f5af65ac 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -11,28 +11,32 @@ import Control.Monad.State import Data.Set qualified as Set import Data.Vector.Strict qualified as Vec -newtype Els e = Els {unEls :: Trie (V.El e)} +data Els e + = Scalar (V.El e) + | Cons (Dict (Els e)) + | Erased -leaf :: V.El e -> Els e -leaf = Els . Leaf +getScalar :: Els e -> V.El e +getScalar (Scalar v) = v +getScalar _ = panic "tried to get leaf value of non-leaf" -getLeaf :: Els e -> V.El e -getLeaf (Els (Leaf v)) = v -getLeaf _ = panic "tried to get leaf value of non-leaf" - -node :: Dict a -> [Els e] -> Els e -node d vs = Els $ Node $ Dict d.head (fromList $ (.unEls) <$> vs) +asAtomHead :: Els e -> Maybe (V.El e) +asAtomHead (Scalar v) = Just v +asAtomHead Erased = Nothing +asAtomHead _ = panic "tried to get leaf value of non-leaf" proj :: Els e -> Name -> Els e -proj (Els (Node fields)) x = Els $ elemAt fields x -proj (Els (Leaf _)) _ = panic "tried to project from non-node" +proj (Cons fields) x = elemAt fields x +proj Erased _ = Erased +proj (Scalar _) _ = panic "tried to project from non-node" concatEls :: [Els e] -> [V.El e] concatEls vs = toList $ go vs BwdNil where go [] vs' = vs' - go ((Els (Leaf v)) : rest) vs' = go rest (vs' :> v) - go ((Els (Node d)) : rest) vs' = go rest (go (Els <$> toList d.values) vs') + go (Scalar v : rest) vs' = go rest (vs' :> v) + go (Cons d : rest) vs' = go rest (go (toList d.values) vs') + go (Erased : rest) vs' = go rest vs' newtype Props e = Props {apply :: Bwd (V.Prop e) -> Bwd (V.Prop e)} @@ -69,10 +73,11 @@ freshAt p = \case aux <- get let i = aux.length put $ aux{vars = (aux.vars :> (p, t)), length = (i + 1)} - pure $ leaf $ V.LocalVar $ FId i + pure $ Scalar $ V.LocalVar $ FId i S.Tuple fields -> do fields' <- forM (toList fields) $ \(x, sh) -> freshAt (p :> x) sh - pure $ node fields fields' + pure $ Cons $ withHead fields fields' + S.Unstored -> pure Erased fresh :: Maybe Name -> S.Shape -> FlatM e (Els e) fresh mx sh = do @@ -113,18 +118,20 @@ instance Flatten (S.El Set) Els where pure $ proj v x S.Cons fields -> do fields' <- forM (toList fields) $ \(_, t) -> flatten l t - pure $ node fields fields' - S.Lit l -> pure $ leaf $ V.Lit l + pure $ Cons $ withHead fields fields' + S.Lit l -> pure $ Scalar $ V.Lit l + S.Erased -> pure Erased equate :: S.Shape -> Els e -> Els e -> Props e -equate (S.Scalar _) v0 v1 = single $ V.PEq (getLeaf v0) (getLeaf v1) +equate (S.Scalar _) v0 v1 = single $ V.PEq (getScalar v0) (getScalar v1) equate (S.Tuple fs) v0 v1 = mconcat [equate t (proj v0 x) (proj v1 x) | (x, t) <- toList fs] +equate S.Unstored _ _ = mempty instance Flatten S.Prop Props where flatten l = \case - S.Atom tn mt args -> do - mv <- traverse (\t -> getLeaf <$> flatten l t) mt + S.Atom tn t args -> do + mv <- asAtomHead <$> flatten l t argvs <- traverse (flatten l) args pure $ single $ V.PAtom (V.Atom tn mv (Just <$> concatEls argvs)) S.And ps -> mconcat <$> traverse (flatten l) (toList ps.values) @@ -137,6 +144,7 @@ flattenColumn :: V.ColName -> S.Shape -> [(V.ColName, V.ColType)] flattenColumn p = \case S.Scalar t -> [(p, t)] S.Tuple d -> concat [flattenColumn (p :> x) t | (x, t) <- toList d] + S.Unstored -> [] flattenColumns :: [(Name, S.Shape)] -> [(V.ColName, V.ColType)] flattenColumns = concat . fmap (\(x, sh) -> flattenColumn (BwdNil :> x) sh) diff --git a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs index a9ebb883..1cd93feb 100644 --- a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs +++ b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs @@ -25,18 +25,19 @@ instance Eval (S.El l) (V.El l) where S.Cons fields -> V.Cons (eval vs <$> fields) S.Proj t x -> V.proj (eval vs t) x S.Lit l -> V.Lit l + S.Erased -> V.Erased instance Eval (S.Ty l) (V.Ty l) where eval vs = \case S.LiftTy t -> V.LiftTy LSetTheory (eval vs t) S.U u -> V.U u - S.EltOf tn args -> V.EltOf tn (eval vs <$> args) + S.EltOf u tn args -> V.EltOf u tn (eval vs <$> args) S.Function ft -> V.Function $ - V.FunctionType SSetTheory (eval vs ft.dom) (evalAbs vs ft.cod) + V.FunctionType ft.variant (eval vs ft.dom) (evalAbs vs ft.cod) S.Record rt -> V.Record $ - V.RecordType vs $ + V.RecordType rt.hlevel vs $ flip eval <$> rt.fieldTypes S.BuiltinTy t -> V.BuiltinTy t S.Eq at lhs rhs -> V.Eq (eval vs at) (eval vs lhs) (eval vs rhs) diff --git a/packages/coln-compiler/src/Coln/MIR/Interpret.hs b/packages/coln-compiler/src/Coln/MIR/Interpret.hs index e742ae96..52348657 100644 --- a/packages/coln-compiler/src/Coln/MIR/Interpret.hs +++ b/packages/coln-compiler/src/Coln/MIR/Interpret.hs @@ -54,9 +54,9 @@ instance Interp (S.Ty c) V.Ty where let cod = case ft.cod of S.Abs x body -> V.Clo x (\v -> interpAt c g (e :> Pair d v) body) S.AbsConst body -> V.CloConst (interpAt c g e body) - Pair c (V.Function (V.FunctionType sfv dom cod)) + Pair c (V.Function (V.FunctionType (SFunctionVariant sfv ft.variant.hlevel) dom cod)) S.Record rt -> withLevel rt.level.mlevel $ \sl -> do - let rt' = V.RecordType e (flip (interpAt sl g) <$> rt.fieldTypes) + let rt' = V.RecordType rt.level.hlevel e (flip (interpAt sl g) <$> rt.fieldTypes) Pair sl (V.Record rt') S.Eq et -> do let at = interpAt SSet g e et.at diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs index 87035412..7fa7553a 100644 --- a/packages/coln-compiler/src/Coln/MIR/Layout.hs +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -51,7 +51,7 @@ bind sc x a = do , names = sc.names :> x , ctx = sc.ctx :> a , bound = sc.bound :> v - , locals = sc.locals :> (Pair SSet v) + , locals = sc.locals :> Pair SSet v , usedNames = Set.insert x sc.usedNames , realm = sc.realm } @@ -67,8 +67,8 @@ layout p sc = \case (gt, M.liftEl $ M.lookup (TableName sc.realm p) (args sc) (M.fromV sc.len a)) V.U (inferSetCodes -> u) -> do let gt = Leaf (Rel u sc.names sc.ctx) - (gt, M.code u $ M.eltOf (TableName sc.realm p) (args sc)) - V.Function ft -> case ft.variant of + (gt, M.code u $ M.eltOf u (TableName sc.realm p) (args sc)) + V.Function ft -> case ft.variant.mlevel of SSetTheory -> do let x = argName sc.usedNames ft.cod let (v, sc') = bind sc x ft.dom diff --git a/packages/coln-compiler/src/Coln/MIR/Memoed.hs b/packages/coln-compiler/src/Coln/MIR/Memoed.hs index 2957b23e..5c34cab5 100644 --- a/packages/coln-compiler/src/Coln/MIR/Memoed.hs +++ b/packages/coln-compiler/src/Coln/MIR/Memoed.hs @@ -31,8 +31,8 @@ lookup tn args a = M (S.Lookup tn ((.stx) <$> args) a.stx) (V.lookup tn ((.val) code :: SUniverse Set Theory -> Ty Set -> El Theory code u (M s v) = M (S.Code u s) (V.Code u v) -eltOf :: TableName -> [El Set] -> Ty Set -eltOf tn args = M (S.EltOf tn ((.stx) <$> args)) (V.EltOf tn ((.val) <$> args)) +eltOf :: SUniverse Set Theory -> TableName -> [El Set] -> Ty Set +eltOf u tn args = M (S.EltOf u tn ((.stx) <$> args)) (V.EltOf u tn ((.val) <$> args)) lam :: V.Locals -> Ty Set -> S.Abs (S.El Theory) -> El Theory lam vs dom abs = do diff --git a/packages/coln-compiler/src/Coln/MIR/Params.hs b/packages/coln-compiler/src/Coln/MIR/Params.hs index e416b117..017401ff 100644 --- a/packages/coln-compiler/src/Coln/MIR/Params.hs +++ b/packages/coln-compiler/src/Coln/MIR/Params.hs @@ -14,6 +14,11 @@ withLevel l f = case l of Theory -> f STheory Top -> f STop +data SLevel (l :: MLevel) = SLevel + { mlevel :: SMLevel l + , hlevel :: HLevel + } + class LevelCoerce (f :: MLevel -> Type) where levelCoerce :: SMLevel l0 -> SMLevel l1 -> f l0 -> f l1 @@ -51,21 +56,29 @@ inferSetCodes :: SUniverse l Theory -> SUniverse Set Theory inferSetCodes SSetU = SSetU inferSetCodes SPropU = SPropU -data SFunctionVariant :: MLevel -> MLevel -> Type where - SSetTheory :: SFunctionVariant Set Theory - STheoryTop :: SFunctionVariant Theory Top +data SMFunctionVariant :: MLevel -> MLevel -> Type where + SSetTheory :: SMFunctionVariant Set Theory + STheoryTop :: SMFunctionVariant Theory Top -sDom :: SFunctionVariant l0 l1 -> SMLevel l0 +sDom :: SMFunctionVariant l0 l1 -> SMLevel l0 sDom = \case SSetTheory -> SSet STheoryTop -> STheory -sCod :: SFunctionVariant l0 l1 -> SMLevel l1 +sCod :: SMFunctionVariant l0 l1 -> SMLevel l1 sCod = \case SSetTheory -> STheory STheoryTop -> STop -withFunctionVariant :: FunctionVariantMLevel -> (forall l0 l1. SFunctionVariant l0 l1 -> a) -> a +withFunctionVariant :: FunctionVariantMLevel -> (forall l0 l1. SMFunctionVariant l0 l1 -> a) -> a withFunctionVariant fv f = case fv of SetTheory -> f SSetTheory TheoryTop -> f STheoryTop + +data SFunctionVariant (l0 :: MLevel) (l1 :: MLevel) = SFunctionVariant + { mlevel :: SMFunctionVariant l0 l1 + , hlevel :: HLevel + } + +instance HLevelOf (SFunctionVariant l0 l1) where + hlevelOf sfv = sfv.hlevel diff --git a/packages/coln-compiler/src/Coln/MIR/Readback.hs b/packages/coln-compiler/src/Coln/MIR/Readback.hs index b19343a1..88224e7d 100644 --- a/packages/coln-compiler/src/Coln/MIR/Readback.hs +++ b/packages/coln-compiler/src/Coln/MIR/Readback.hs @@ -24,13 +24,14 @@ instance Readback (V.El Set) (S.El Set) where go (readb n ne.head) ne.spine V.Cons fields -> S.Cons $ readb n <$> fields V.Lit l -> S.Lit l + V.Erased -> S.Erased fresh :: CtxLen -> V.El Set fresh n = V.local (FId n) instance Readback (V.Ty Set) (S.Ty Set) where readb n = \case - V.EltOf tn args -> S.EltOf tn (readb n <$> args) + V.EltOf u tn args -> S.EltOf u tn (readb n <$> args) V.BuiltinTy t -> S.BuiltinTy t V.Eq at lhs rhs -> S.Eq (readb n at) (readb n lhs) (readb n rhs) V.Record rt -> do @@ -38,7 +39,7 @@ instance Readback (V.Ty Set) (S.Ty Set) where go n' vs ((x, k) : rest) = (x, readb n' (k vs)) : (go (n' + 1) (vs :> Pair SSet (fresh n')) rest) let fieldTypes = fromList $ go n rt.capture (toList rt.fieldTypes) - S.Record $ S.RecordType fieldTypes + S.Record $ S.RecordType rt.hlevel fieldTypes instance Readback (V.Ty Theory) (S.Ty Theory) where readb n = \case diff --git a/packages/coln-compiler/src/Coln/MIR/Syntax.hs b/packages/coln-compiler/src/Coln/MIR/Syntax.hs index b11fc066..febbc5e1 100644 --- a/packages/coln-compiler/src/Coln/MIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/MIR/Syntax.hs @@ -15,19 +15,23 @@ data El :: MLevel -> Type where Cons :: Dict (El l) -> El l Proj :: El l -> Name -> El l Lit :: Literal -> El Set + Erased :: El Set data FunctionType = FunctionType - { dom :: Ty Set + { variant :: SFunctionVariant Set Theory + , dom :: Ty Set , cod :: Abs (Ty Theory) } data RecordType l = RecordType - {fieldTypes :: Dict (Ty l)} + { hlevel :: HLevel + , fieldTypes :: Dict (Ty l) + } data Ty :: MLevel -> Type where LiftTy :: Ty Set -> Ty Theory U :: SUniverse Set Theory -> Ty Theory - EltOf :: TableName -> [El Set] -> Ty Set + EltOf :: SUniverse Set Theory -> TableName -> [El Set] -> Ty Set Function :: FunctionType -> Ty Theory Record :: RecordType l -> Ty l BuiltinTy :: BuiltinTy -> Ty Set diff --git a/packages/coln-compiler/src/Coln/MIR/Value.hs b/packages/coln-compiler/src/Coln/MIR/Value.hs index a72ed80d..d2f7c97b 100644 --- a/packages/coln-compiler/src/Coln/MIR/Value.hs +++ b/packages/coln-compiler/src/Coln/MIR/Value.hs @@ -29,9 +29,10 @@ data El :: MLevel -> Type where LiftEl :: Lift l0 l1 -> El l0 -> El l1 Neu :: Neutral -> El Set Code :: SUniverse l0 l1 -> Ty l0 -> El l1 - Lam :: SFunctionVariant l0 l1 -> Ty l0 -> Clo (El l0) (El l1) -> El l1 + Lam :: SMFunctionVariant l0 l1 -> Ty l0 -> Clo (El l0) (El l1) -> El l1 Cons :: Dict (El l) -> El l Lit :: Literal -> El Set + Erased :: El Set local :: FId -> El Set local i = Neu $ Neutral (Var i) BwdNil @@ -39,7 +40,7 @@ local i = Neu $ Neutral (Var i) BwdNil lookup :: TableName -> [El Set] -> Ty Set -> El Set lookup tn args a = Neu $ Neutral (Lookup tn args a) BwdNil -app :: SFunctionVariant l0 l1 -> El l1 -> El l0 -> El l1 +app :: SMFunctionVariant l0 l1 -> El l1 -> El l0 -> El l1 app fv (Lam fv' _ clo) v = case (fv, fv') of (SSetTheory, SSetTheory) -> appClo clo v (STheoryTop, STheoryTop) -> appClo clo v @@ -48,6 +49,7 @@ app _ _ _ = panic "can only apply lambda" proj :: El l -> Name -> El l proj (Neu n) x = Neu $ n{spine = n.spine :> x} proj (Cons fields) x = elemAt fields x +proj Erased _ = Erased proj _ _ = panic "can only project from neutral or cons" decode :: SUniverse l0 l1 -> El l1 -> Ty l0 @@ -78,14 +80,15 @@ data FunctionType (l0 :: MLevel) (l1 :: MLevel) = FunctionType } data RecordType (l :: MLevel) = RecordType - { capture :: Locals + { hlevel :: HLevel + , capture :: Locals , fieldTypes :: Dict (Locals -> Ty l) } data Ty :: MLevel -> Type where LiftTy :: Lift l0 l1 -> Ty l0 -> Ty l1 U :: SUniverse l0 l1 -> Ty l1 - EltOf :: TableName -> [El Set] -> Ty Set + EltOf :: SUniverse Set Theory -> TableName -> [El Set] -> Ty Set Function :: FunctionType l0 l1 -> Ty l1 Record :: RecordType l -> Ty l BuiltinTy :: BuiltinTy -> Ty Set @@ -102,3 +105,11 @@ instance LevelCoerce Ty where levelCoerce STop STheory (LiftTy LTheoryTop v) = v levelCoerce STop SSet (LiftTy LTheoryTop (LiftTy LSetTheory v)) = v levelCoerce _ _ _ = panic "cannot lift" + +instance HLevelOf (Ty Set) where + hlevelOf = \case + EltOf SPropU _ _ -> HProp + EltOf SSetU _ _ -> HSet + Record rt -> rt.hlevel + Eq eat _ _ -> equalityHLevelOf (hlevelOf eat) + BuiltinTy _ -> HSet diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs index 595f6a4d..0a5ed4fc 100644 --- a/packages/coln-compiler/src/Coln/SIR/Cache.hs +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -54,7 +54,7 @@ cache p sc v = do let ent = Entity View (zip xs ((.shape) <$> cols)) (Just [0 .. sc.len]) let tn = TableName sc.realm p let def = Definition (zip xs cols) tn boundStx - let prop = S.Atom tn Nothing boundStx + let prop = S.Atom tn S.Erased boundStx let elt = S.Multi u $ S.Query sa.shape (S.Abs Nothing prop) (Leaf ent, Node (fromList [("definition", Leaf def)]), elt) case v of diff --git a/packages/coln-compiler/src/Coln/SIR/Realm.hs b/packages/coln-compiler/src/Coln/SIR/Realm.hs index 11da8f5c..751d0799 100644 --- a/packages/coln-compiler/src/Coln/SIR/Realm.hs +++ b/packages/coln-compiler/src/Coln/SIR/Realm.hs @@ -22,8 +22,11 @@ data Definition = Definition data RuleVariant = Enforced | Monitored +data RuleContextSide = Antecedent | Consequent + data Rule = Rule { ruleVariant :: RuleVariant + , ctxSide :: RuleContextSide , inCtx :: [(Name, Query)] , antecedent :: Prop , consequent :: Prop diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs index 5bcce5ce..7d7a6ffa 100644 --- a/packages/coln-compiler/src/Coln/SIR/Separate.hs +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -3,7 +3,9 @@ module Coln.SIR.Separate where import Coln.Common import Coln.Core.Params import Coln.MIR.Params +import Coln.MIR.Realm qualified as V import Coln.MIR.Value qualified as V +import Coln.SIR.Realm import Coln.SIR.Syntax qualified as S type CtxLen = Int @@ -16,7 +18,7 @@ instance Separate V.Head (S.El Set) where V.Var (FId i) -> S.Var (BId (n - i - 1)) V.Lookup tn args ret -> do let args' = separate n <$> args - let pred = S.Atom tn Nothing (args' ++ [S.Var 0]) + let pred = S.Atom tn S.Erased (args' ++ [S.Var 0]) S.Single $ S.Query (shapeOf ret) (S.Abs Nothing pred) instance Separate (V.El Set) (S.El Set) where @@ -27,6 +29,7 @@ instance Separate (V.El Set) (S.El Set) where go (separate n ne.head) ne.spine V.Cons fields -> S.Cons $ separate n <$> fields V.Lit l -> S.Lit l + V.Erased -> S.Erased separateClo :: (Separate a b) => CtxLen -> V.Clo (V.El Set) a -> S.Abs b separateClo n (V.Clo x body) = S.Abs (Just x) (separate (n + 1) (body (V.local (FId n)))) @@ -42,26 +45,27 @@ instance Separate (V.El Theory) (S.El Theory) where shapeOf :: V.Ty Set -> S.Shape shapeOf = \case - V.EltOf x _ -> S.Scalar $ S.RowId x + V.EltOf SPropU _ _ -> S.Unstored + V.EltOf SSetU x _ -> S.Scalar $ S.RowId x V.Record rt -> do let go [] _ _ = [] go ((x, k) : rest) vs v = do let v' = V.proj v x - (x, shapeOf (k vs)) : (go rest (vs :> Pair SSet v') v) + (x, shapeOf (k vs)) : go rest (vs :> Pair SSet v') v let v = V.local (FId 0) S.Tuple $ fromList $ go (toList rt.fieldTypes) rt.capture v V.BuiltinTy t -> S.Scalar $ S.BuiltinTy t - V.Eq _ _ _ -> S.unitShape + V.Eq _ _ _ -> S.Unstored propAt :: CtxLen -> V.Ty Set -> V.El Set -> S.Prop propAt n = \case - V.EltOf x args -> \v -> - S.Atom x (Just (separate n v)) (separate n <$> args) + V.EltOf _ x args -> \v -> + S.Atom x (separate n v) (separate n <$> args) V.Record rt -> \v -> do let go [] _ = [] go ((x, k) : rest) vs = do let v' = V.proj v x - (x, propAt n (k vs) v') : (go rest (vs :> Pair SSet v')) + (x, propAt n (k vs) v') : go rest (vs :> Pair SSet v') S.And $ fromList $ go (toList rt.fieldTypes) rt.capture V.BuiltinTy _ -> \_ -> S.trueProp V.Eq at lhs rhs -> \_ -> @@ -70,3 +74,40 @@ propAt n = \case instance Separate (V.Ty Set) S.Query where separate n a = S.Query (shapeOf a) (S.Abs Nothing (propAt (n + 1) a (V.local (FId n)))) + +separateGenerator :: TableName -> V.Generator -> Realm +separateGenerator tn = \case + V.Rel u xs tys -> do + let names = toList xs + let argNum = length names + let septys = uncurry separate <$> zip [0 ..] (toList tys) + let primaryKey = case u of + SSetU -> Nothing + SPropU -> Just [0 .. argNum - 1] + let table = Entity Table (zip names ((.shape) <$> septys)) primaryKey + let atom = S.Atom tn S.Erased [S.Var (BId (argNum - i - 1)) | i <- [0 .. argNum - 1]] + let foreignKey = Rule Enforced Consequent (zip names septys) atom S.trueProp + Realm{entities = Leaf table, definitions = Node $ fromList [], rules = Leaf foreignKey} + V.Fun xs tys cod -> case hlevelOf cod of + HUnit -> Realm{entities = Node $ fromList [], definitions = Node $ fromList [], rules = Node $ fromList []} + HProp -> do + let names = toList xs + let argNum = length names + let septys = uncurry separate <$> zip [0 ..] (toList tys) + let codProp = propAt argNum cod V.Erased + let rule = Rule Monitored Antecedent (zip names septys) S.trueProp codProp + Realm{entities = Node $ fromList [], definitions = Node $ fromList [], rules = Leaf rule} + HSet -> do + let names = toList xs + let argNum = length names + let septys = uncurry separate <$> zip [0 ..] (toList (tys :> cod)) + let table = Entity Table (zip names ((.shape) <$> septys)) (Just [0 .. argNum - 1]) + let foreignKeyAnte = S.Atom tn S.Erased [S.Var (BId (argNum - i - 1)) | i <- [0 .. argNum]] + let foreignKey = Rule Enforced Consequent (zip names septys) foreignKeyAnte S.trueProp + let totalCons = S.Atom tn S.Erased [S.Var (BId (argNum - i - 1)) | i <- [0 .. argNum - 1]] + let total = Rule Monitored Antecedent (zip names (take argNum septys)) S.trueProp totalCons + Realm{entities = Leaf table, definitions = Node $ fromList [], rules = Node $ fromList [("foreignKey", Leaf foreignKey), ("total", Leaf total)]} + _ -> panic "bad h-level of cod" + +-- separateRealm :: V.Realm -> Realm +-- separateRealm r = _ diff --git a/packages/coln-compiler/src/Coln/SIR/Syntax.hs b/packages/coln-compiler/src/Coln/SIR/Syntax.hs index 2774bfc3..22cbe5b9 100644 --- a/packages/coln-compiler/src/Coln/SIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/SIR/Syntax.hs @@ -15,9 +15,10 @@ data El :: MLevel -> Type where Lam :: Query -> Abs (El Theory) -> El Theory Cons :: Dict (El l) -> El l Lit :: Literal -> El Set + Erased :: El Set data Prop - = Atom TableName (Maybe (El Set)) [El Set] + = Atom TableName (El Set) [El Set] | And (Dict Prop) | Eq Shape (El Set) (El Set) @@ -29,14 +30,13 @@ data ScalarType data Shape = Tuple (Dict Shape) | Scalar ScalarType + | Unstored shapeSize :: Shape -> Int shapeSize = \case Tuple ds -> sum $ shapeSize <$> toList ds.values Scalar _ -> 1 - -unitShape :: Shape -unitShape = Tuple (fromList []) + Unstored -> 0 trueProp :: Prop trueProp = And (fromList []) From 2191f93ee1656f489dde33b2338b90b248645ed2 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Fri, 21 Aug 2026 12:29:04 +0100 Subject: [PATCH 09/42] stuff --- .../src/Coln/Backend/TypeScript/Generate.hs | 218 +++++++++--------- packages/coln-compiler/src/Coln/SIR/Cache.hs | 2 +- 2 files changed, 110 insertions(+), 110 deletions(-) diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs index 337a0abb..c299e114 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs @@ -5,127 +5,127 @@ module Coln.Backend.TypeScript.Generate where -- import Control.Monad (forM_) --- import Control.Monad.State +import Control.Monad.State -- import Data.Aeson qualified as AE -- import Data.Foldable (foldlM) -- import Data.Foldable qualified as F -- import Data.Map.Ordered qualified as OMap --- import Data.Set (Set) --- import Data.String (IsString (..)) +import Data.Set qualified as Set +import Data.String (IsString (..)) -- import Data.Text.Lazy qualified as TL -- import Data.Text.Lazy.IO qualified as TLIO -- import Prettyprinter -- import Prettyprinter.Render.Text -- import System.FilePath --- import Coln.Backend.TypeScript.AST qualified as TS +import Coln.Backend.TypeScript.AST qualified as TS -- import Coln.Backend.TypeScript.Assemble (asm) --- import Coln.Backend.TypeScript.Params --- import Coln.Common +import Coln.Backend.TypeScript.Params +import Coln.Common -- import Coln.Core.Globals --- import Coln.Core.Memoed --- import Coln.Core.Params --- import Coln.Core.Readback --- import Coln.Core.Value qualified as V - --- mangle :: Name -> TS.Id --- mangle = TS.Id . mangleToDoc - --- tyFromHead :: Access -> V.Head -> TS.Ty --- tyFromHead access (V.GlobalVar x _) = --- TS.TyConst (TS.QId [mangle x] (fromString (show access))) --- tyFromHead access (V.LocalVar _) = TS.runtime $ ColnRef access --- tyFromHead _ (V.Lookup _ _ _) = panic "table lookup cannot be used as a type" - --- genTy :: Access -> CtxLen -> V.Ty N -> TS.Ty --- genTy access n = \case --- V.U (SetU; PropU) -> TS.runtime (ColnSet access) --- V.Function ft -> do --- let v = V.local (FId n) ft.dom --- TS.Fun (TS.Binding (TS.Id "x") (TS.runtime Value)) (genTy access (n + 1) (V.appClo ft.cod v)) --- V.EltOf _ _ -> TS.runtime $ ColnRef access --- V.Decode n -> tyFromHead access n.head --- V.BuiltinTy _ -> TS.runtime $ ColnRef access --- _ -> error "not yet supported" - --- genInterface :: Access -> CtxLen -> V.Ty D -> TS.Interface --- genInterface access n = \case --- V.Record rt -> do --- let name = fromString $ show access --- let extendsName = fromString . show <$> extends access --- TS.Interface name extendsName (go n rt.capture (toList rt.fieldTypes)) --- where --- go _ _ [] = [] --- go n' vs ((x, f) : rest) = do --- let a = f vs --- let v = V.local (FId n') a --- let bnd = TS.Binding (mangle x) (genTy access n' a) --- bnd : go (n' + 1) (V.LSnoc vs v) rest - --- class TrackGlobals a where --- trackGlobals :: a -> State (Set Name) () - --- -- instance TrackGlobals (f c) => TrackGlobals (S.Abs f c) where --- -- trackGlobals abs = trackGlobals (absBody abs) - --- -- instance TrackGlobals a => TrackGlobals (Name, a) where --- -- trackGlobals (_, t) = trackGlobals t - --- -- instance TrackGlobals (S.El c) where --- -- trackGlobals = \case --- -- S.LocalVar _ -> pure () --- -- S.GlobalVar x _ -> modify (Set.insert x) --- -- S.Code a -> trackGlobals a --- -- S.Lam dom body -> do --- -- trackGlobals dom --- -- trackGlobals body --- -- S.App t0 t1 -> do --- -- trackGlobals t0 --- -- trackGlobals t1 --- -- S.Cons ts -> mapM_ trackGlobals (toList ts) --- -- S.Proj t _ -> trackGlobals t --- -- S.Lit _ -> pure () --- -- S.Is t -> trackGlobals t --- -- S.Lookup _ _ -> pure () - --- -- instance TrackGlobals (S.Ty c) where --- -- trackGlobals = \case --- -- S.U _ -> pure () --- -- S.Decode t -> trackGlobals t --- -- S.Function ft -> do --- -- trackGlobals ft.dom --- -- trackGlobals ft.cod --- -- S.Record rt -> mapM_ trackGlobals (toList rt.fieldTypes) --- -- S.Eq et -> do --- -- trackGlobals et.lhs --- -- trackGlobals et.rhs --- -- S.BuiltinTy _ -> pure () --- -- S.IsTy a -> trackGlobals a --- -- S.EltOf _ _ -> pure () - --- genTypeDef :: Access -> CtxLen -> V.Ty N -> TS.TypeDef --- genTypeDef access n a = TS.TypeDef (fromShow access) (genTy access n a) - --- genEntryModule :: [TS.Import] -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module --- genEntryModule imports a ev = go 0 a ev --- where --- go :: CtxLen -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module --- go n (V.U TheoryU) ev' = do --- let definitions = for accessLevels $ \access -> --- case V.ebind V.decode ev' of --- V.Become a -> TS.DTypeDef $ genTypeDef access n a --- V.Describe a -> TS.DInterface $ genInterface access n a --- V.BecomeWith _ -> panic "can't lower becomewith yet" --- Just $ TS.Module imports (TS.Exported <$> definitions) --- go n (V.Function ft) ev' = do --- let v = V.local (FId n) ft.dom --- go (n + 1) (V.appClo ft.cod v) (V.ebind (flip V.app v) ev') --- go _ _ _ = Nothing - --- data TSCtxShape = TSCtxShape --- { len :: CtxLen --- , names :: Bwd TS.Id --- } + +import Coln.Core.Params +import Coln.Core.Readback +import Coln.Core.Value qualified as V +import Coln.Core.Syntax qualified as S +-- import Coln.SIR.Syntax qualified as S + +mangle :: Name -> TS.Id +mangle = TS.Id . mangleToDoc + +tyFromHead :: Access -> V.Head -> TS.Ty +tyFromHead access (V.GlobalVar x _) = + TS.TyConst (TS.QId [mangle x] (fromString (show access))) +tyFromHead access (V.LocalVar _) = TS.runtime $ ColnRef access + +genTy :: Access -> CtxLen -> V.Ty N -> TS.Ty +genTy access n = \case + V.U (SetU; PropU) -> TS.runtime (ColnSet access) + V.Function ft -> do + let v = V.local (FId n) ft.dom + TS.Fun (TS.Binding (TS.Id "x") (TS.runtime Value)) (genTy access (n + 1) (V.appClo ft.cod v)) + V.Decode n -> tyFromHead access n.head + V.BuiltinTy _ -> TS.runtime $ ColnRef access + _ -> error "not yet supported" + +genInterface :: Access -> CtxLen -> V.Ty D -> TS.Interface +genInterface access n = \case + V.Record rt -> do + let name = fromString $ show access + let extendsName = fromString . show <$> extends access + TS.Interface name extendsName (go n rt.capture (toList rt.fieldTypes)) + where + go _ _ [] = [] + go n' vs ((x, f) : rest) = do + let a = f vs + let v = V.local (FId n') a + let bnd = TS.Binding (mangle x) (genTy access n' a) + bnd : go (n' + 1) (V.LSnoc vs v) rest + +class TrackGlobals a where + trackGlobals :: a -> State (Set.Set Name) () + +instance TrackGlobals (f c) => TrackGlobals (S.Abs f c) where + trackGlobals (S.Abs _ body) = trackGlobals body + trackGlobals (S.AbsConst body) = trackGlobals body + +instance TrackGlobals a => TrackGlobals (Name, a) where + trackGlobals (_, t) = trackGlobals t + +instance TrackGlobals (S.El c) where + trackGlobals = \case + S.LocalVar _ -> pure () + S.GlobalVar x _ -> modify (Set.insert x) + S.Code _ a -> trackGlobals a + S.Lam _ dom body -> do + trackGlobals dom + trackGlobals body + S.App _ t0 t1 -> do + trackGlobals t0 + trackGlobals t1 + S.Cons _ ts -> mapM_ trackGlobals (toList ts) + S.Proj _ t _ -> trackGlobals t + S.Init _ -> pure () + S.Lit _ -> pure () + S.Is t -> trackGlobals t + +instance TrackGlobals (S.Ty c) where + trackGlobals = \case + S.U _ -> pure () + S.Decode _ t -> trackGlobals t + S.Function ft -> do + trackGlobals ft.dom + trackGlobals ft.cod + S.Record rt -> mapM_ trackGlobals (toList rt.fieldTypes) + S.Eq et -> do + trackGlobals et.lhs + trackGlobals et.rhs + S.BuiltinTy _ -> pure () + S.IsTy a -> trackGlobals a + +genTypeDef :: Access -> CtxLen -> V.Ty N -> TS.TypeDef +genTypeDef access n a = TS.TypeDef (fromShow access) (genTy access n a) + +genEntryModule :: [TS.Import] -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module +genEntryModule imports a ev = go 0 a ev + where + go :: CtxLen -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module + go n (V.U TheoryU) ev' = do + let definitions = for accessLevels $ \access -> + case V.ebind V.decode ev' of + V.Become a -> TS.DTypeDef $ genTypeDef access n a + V.Describe a -> TS.DInterface $ genInterface access n a + V.BecomeWith _ -> panic "can't lower becomewith yet" + Just $ TS.Module imports (TS.Exported <$> definitions) + go n (V.Function ft) ev' = do + let v = V.local (FId n) ft.dom + go (n + 1) (V.appClo ft.cod v) (V.ebind (flip (V.app ft.variant) v) ev') + go _ _ _ = Nothing + +data TSCtxShape = TSCtxShape + { len :: CtxLen + , names :: Bwd TS.Id + } -- emptyTSCtxShape :: TSCtxShape -- emptyTSCtxShape = TSCtxShape 0 BwdNil diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs index 0a5ed4fc..8e8afd7f 100644 --- a/packages/coln-compiler/src/Coln/SIR/Cache.hs +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -60,7 +60,7 @@ cache p sc v = do case v of V.LiftEl LSetTheory v -> (emptyNode, emptyNode, S.LiftEl (separate sc.len v)) V.Code SSetU a -> code SSetU a - V.Code SPropU a -> code SSetU a + V.Code SPropU a -> code SPropU a V.Lam SSetTheory dom clo -> do let (x, arg, sc') = bind sc (cloArgName clo) dom let (ents, defs, body) = cache p sc' (V.appClo clo arg) From 13c3cb63549c3354124b21372d6c53f8a30dac1f Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Mon, 24 Aug 2026 16:20:12 +0100 Subject: [PATCH 10/42] saving version with direct injection into query params --- .../src/Coln/Backend/TypeScript/AST.hs | 1 + .../src/Coln/Backend/TypeScript/Generate.hs | 172 ++++++++++++------ .../src/Coln/Backend/TypeScript/Params.hs | 1 + packages/coln-compiler/src/Coln/Common.hs | 7 + .../coln-compiler/src/Coln/FLIR/Flatten.hs | 23 ++- 5 files changed, 138 insertions(+), 66 deletions(-) diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/AST.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/AST.hs index 4a5e78ed..8903aca3 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/AST.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/AST.hs @@ -71,6 +71,7 @@ data El | Index El Int | Not El | Object [(Id, El)] + | Null data Statement = Let Id El diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs index c299e114..ca4487dc 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs @@ -14,7 +14,7 @@ import Data.Set qualified as Set import Data.String (IsString (..)) -- import Data.Text.Lazy qualified as TL -- import Data.Text.Lazy.IO qualified as TLIO --- import Prettyprinter +import Prettyprinter -- import Prettyprinter.Render.Text -- import System.FilePath @@ -28,7 +28,9 @@ import Coln.Core.Params import Coln.Core.Readback import Coln.Core.Value qualified as V import Coln.Core.Syntax qualified as S --- import Coln.SIR.Syntax qualified as S +import Coln.SIR.Syntax qualified as SIR +import Coln.FLIR.Flatten qualified as FLIR +import Coln.FLIR.Value qualified as FLIR mangle :: Name -> TS.Id mangle = TS.Id . mangleToDoc @@ -122,66 +124,116 @@ genEntryModule imports a ev = go 0 a ev go (n + 1) (V.appClo ft.cod v) (V.ebind (flip (V.app ft.variant) v) ev') go _ _ _ = Nothing -data TSCtxShape = TSCtxShape - { len :: CtxLen - , names :: Bwd TS.Id +data TSEnv = TSEnv + { locals :: Bwd TS.El + , usedNames :: Set.Set Name } --- emptyTSCtxShape :: TSCtxShape --- emptyTSCtxShape = TSCtxShape 0 BwdNil - --- bind :: TSCtxShape -> TS.Id -> TSCtxShape --- bind cs x = TSCtxShape{len = cs.len + 1, names = cs.names :> x} - --- tableNameDoc :: TableName -> DDoc --- tableNameDoc tn = concatWith (surround dot) (dpretty <$> (tn.realm : toList tn.path)) - --- genTyVal :: Access -> TSCtxShape -> V.Ty N -> TS.El --- genTyVal access cs = \case --- V.EltOf x vs -> do --- let params = TS.List $ genEl access cs <$> F.toList vs --- let transactionArg = case access of --- View -> [] --- Transaction -> [TS.Var "transaction"] --- let args = [TS.Var "store", TS.String (tableNameDoc x), params] ++ transactionArg --- TS.New (TS.Const (TS.runtime (RowIdSet access))) args --- _ -> panic "composite not yet supported" - --- genHead :: Access -> TSCtxShape -> V.Head -> TS.El --- genHead access cs = \case --- V.LocalVar (FId i) -> TS.Var $ elemAt cs.names (BId (cs.len - i - 1)) --- V.GlobalVar _ _ -> panic "global var neutral not yet supported" --- V.Lookup tn vs _ -> do --- let params = TS.List $ genEl access cs <$> F.toList vs --- let transactionArg = case access of --- View -> [] --- Transaction -> [TS.Var "transaction"] --- let args = [TS.Var "store", TS.String (tableNameDoc tn), params] ++ transactionArg --- TS.New (TS.Const (TS.runtime (TableCellRef access))) args - --- genSp :: TSCtxShape -> V.Spine -> TS.El -> TS.El --- genSp _cs = \case --- V.Id -> \t -> t --- _ -> panic "unsupported spine operation" - --- argName :: TSCtxShape -> V.Clo f c -> TS.Id --- argName _ (V.Clo x _ _) = mangle x --- argName _ (V.CloConst _) = panic "closures from the layout process should have argument names" - --- genEl :: Access -> TSCtxShape -> V.El N -> TS.El --- genEl access cs = \case --- V.Neu n -> genSp cs n.spine $ genHead access cs n.head --- V.InitNeu _ -> panic "can't lower init yet" --- V.Code a -> genTyVal access cs a --- V.Lam dom clo -> do --- let v = V.local (FId cs.len) dom --- let x = argName cs clo --- TS.Lam --- (TS.Binding x (TS.runtime Value)) --- (TS.Block [] (Just (genEl access (bind cs x) (V.appClo clo v)))) --- V.Cons fields -> TS.Object $ for (toList fields) $ \(x, v) -> --- (mangle x, genEl access cs v) --- V.Lit l -> TS.Lit l +instance FLIR.Extern TS.El where + eproj v x = TS.Proj v (mangle x) + +tableNameDoc :: TableName -> DDoc +tableNameDoc tn = concatWith (surround dot) (dpretty <$> (tn.realm : toList tn.path)) + +tagged :: DDoc -> TS.El -> TS.El +tagged x v = TS.Object [("tag", TS.String x), ("value", v)] + +stageEl :: FLIR.El TS.El -> TS.El +stageEl = \case + FLIR.Lit l -> tagged "Lit" $ TS.Lit l + FLIR.LocalVar (FId i) -> tagged "LocalVar" $ TS.Lit $ LitInt i + FLIR.Extern v -> v + +orNull :: (a -> TS.El) -> Maybe a -> TS.El +orNull f (Just x) = f x +orNull _ Nothing = TS.Null + +stageAtom :: FLIR.Atom TS.El -> TS.El +stageAtom a = TS.Object + [ ("entity", TS.String $ tableNameDoc a.entity) + , ("rowId", orNull stageEl a.rowId) + , ("values", TS.List (orNull stageEl <$> a.values)) + ] + +stageProp :: FLIR.Prop TS.El -> TS.El +stageProp = \case + FLIR.PAtom a -> tagged "PAtom" $ stageAtom a + FLIR.PEq v0 v1 -> tagged "PEq" $ TS.Object [("lhs", stageEl v0), ("rhs", stageEl v1)] + +builtinDoc :: BuiltinTy -> DDoc +builtinDoc = \case + BuiltinInt -> "Int" + BuiltinString -> "String" + +genColType :: FLIR.ColType -> TS.El +genColType = \case + SIR.RowId x -> tagged "RowId" $ TS.String $ tableNameDoc x + SIR.BuiltinTy ty -> tagged "BuiltinTy" $ TS.String $ builtinDoc ty + +reconstructEl :: FLIR.El TS.El -> TS.El +reconstructEl = \case + FLIR.LocalVar (FId i) -> TS.Index (TS.Var "result") i + FLIR.Lit l -> TS.Lit l + FLIR.Extern x -> x + +reconstructEls :: FLIR.Els TS.El -> TS.El +reconstructEls = \case + FLIR.Scalar v -> reconstructEl v + FLIR.Cons d -> TS.Object [(mangle x, reconstructEls t) | (x, t) <- toList d] + FLIR.Erased -> TS.Null + +genQuery :: Access -> TSEnv -> SIR.Query -> TS.El +genQuery _access e q = do + let ((v, mainprops), vars, auxprops) = FLIR.runFlatM $ do + v <- FLIR.freshAt (BwdNil :> "result") q.shape + mainprops <- FLIR.app (FLIR.extern <$> e.locals) q.pred v + pure (v, mainprops) + let flir = TS.Object + [ ("vars", TS.List $ genColType . snd <$> vars) + , ("props", TS.List $ stageProp <$> toList (mainprops <> auxprops)) + ] + -- TODO: should make sure "result" is fresh + let reconstruct = + TS.Lam + (TS.Binding "result" (TS.ListTy (TS.runtime Value))) + (TS.Block [] (Just (reconstructEls v))) + TS.New (TS.Const (TS.runtime Query)) [flir, reconstruct] + +varName :: SIR.Abs a -> Set.Set Name -> Name +varName (SIR.Abs (Just x) _) xs = case Set.member x xs of + True -> freshNameFor xs + False -> x +varName _ xs = freshNameFor xs + +genAbs :: Access -> TSEnv -> SIR.Abs (SIR.El l) -> (Name, TS.El) +genAbs access e (SIR.Abs mx body) = do + let x = freshNameWithPref e.usedNames mx + let e' = e + { locals = e.locals :> TS.Var (mangle x) + , usedNames = Set.insert x e.usedNames + } + (x, genEl access e' body) +genAbs access e (SIR.AbsConst body) = do + let x = freshNameFor e.usedNames + let e' = e { usedNames = Set.insert x e.usedNames } + (x, genEl access e' body) + +genEl :: Access -> TSEnv -> SIR.El l -> TS.El +genEl access e = \case + SIR.LiftEl t -> genEl access e t + SIR.Var i -> elemAt e.locals i + SIR.Single q -> TS.MethodCall (genQuery access e q) "single" [] + SIR.Proj t x -> TS.Proj (genEl access e t) (mangle x) + SIR.Multi _ q -> TS.MethodCall (genQuery access e q) "multi" [] + SIR.Lam _dom abs -> do + let (x, body) = genAbs access e abs + TS.Lam + (TS.Binding (mangle x) (TS.runtime Value)) + (TS.Block [] (Just body)) + SIR.Cons fields -> + TS.Object [(mangle x, genEl access e t) | (x, t) <- toList fields] + SIR.Lit l -> TS.Lit l + SIR.Erased -> TS.Null -- genRealmConstructor :: Access -> Realm -> TS.Constructor -- genRealmConstructor access r = do diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Params.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Params.hs index bdd93d9a..b0558f98 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Params.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Params.hs @@ -19,6 +19,7 @@ extends = \case data RuntimeConst = Value + | Query | ColnSet Access | RowIdSet Access | ColnRef Access diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index 96af406d..314c84d4 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -38,6 +38,7 @@ module Coln.Common ( alphaNames, freshNameFor, freshNamesFor, + freshNameWithPref, Match (..), mangleToDoc, mangleToString, @@ -299,6 +300,12 @@ freshNamesFor a = flip filter alphaNames $ flip Set.notMember $ namesIn a freshNameFor :: (HasNames a) => a -> Name freshNameFor = head . freshNamesFor +freshNameWithPref :: (HasNames a) => a -> Maybe Name -> Name +freshNameWithPref a (Just x) = case Set.member x (namesIn a) of + True -> freshNameFor a + False -> x +freshNameWithPref a Nothing = freshNameFor a + -- Any -------------------------------------------------------------------------------- diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index f5af65ac..b24586d4 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -11,11 +11,21 @@ import Control.Monad.State import Data.Set qualified as Set import Data.Vector.Strict qualified as Vec +class Extern e where + eproj :: e -> Name -> e + + +instance Extern Void where + eproj = \case + data Els e = Scalar (V.El e) | Cons (Dict (Els e)) | Erased +extern :: e -> Els e +extern v = Scalar (V.Extern v) + getScalar :: Els e -> V.El e getScalar (Scalar v) = v getScalar _ = panic "tried to get leaf value of non-leaf" @@ -25,10 +35,11 @@ asAtomHead (Scalar v) = Just v asAtomHead Erased = Nothing asAtomHead _ = panic "tried to get leaf value of non-leaf" -proj :: Els e -> Name -> Els e +proj :: Extern e => Els e -> Name -> Els e proj (Cons fields) x = elemAt fields x proj Erased _ = Erased -proj (Scalar _) _ = panic "tried to project from non-node" +proj (Scalar (V.Extern v)) x = Scalar (V.Extern (eproj v x)) +proj (Scalar _) _ = panic "tried to project from non-extern scalar" concatEls :: [Els e] -> [V.El e] concatEls vs = toList $ go vs BwdNil @@ -93,7 +104,7 @@ fresh mx sh = do type Locals e = Bwd (Els e) class Flatten a (b :: Type -> Type) | a -> b where - flatten :: Locals e -> a -> FlatM e (b e) + flatten :: (Extern e) => Locals e -> a -> FlatM e (b e) absName :: S.Abs a -> Maybe Name absName (S.Abs mx _) = mx @@ -102,7 +113,7 @@ absName (S.AbsConst _) = Nothing assert :: Props e -> FlatM e () assert ps = modify (\aux -> aux{props = aux.props <> ps}) -app :: (Flatten a b) => Locals e -> S.Abs a -> Els e -> FlatM e (b e) +app :: (Flatten a b, Extern e) => Locals e -> S.Abs a -> Els e -> FlatM e (b e) app l (S.Abs _ body) v = flatten (l :> v) body app l (S.AbsConst body) _ = flatten l body @@ -122,7 +133,7 @@ instance Flatten (S.El Set) Els where S.Lit l -> pure $ Scalar $ V.Lit l S.Erased -> pure Erased -equate :: S.Shape -> Els e -> Els e -> Props e +equate :: (Extern e) => S.Shape -> Els e -> Els e -> Props e equate (S.Scalar _) v0 v1 = single $ V.PEq (getScalar v0) (getScalar v1) equate (S.Tuple fs) v0 v1 = mconcat [equate t (proj v0 x) (proj v1 x) | (x, t) <- toList fs] @@ -168,7 +179,7 @@ flattenEntity e = , V.primaryKey = fmap (flattenPrimaryKey (snd <$> e.columns)) e.primaryKey } -bindTele :: Locals e -> [(Name, S.Query)] -> FlatM e (Locals e) +bindTele :: (Extern e) => Locals e -> [(Name, S.Query)] -> FlatM e (Locals e) bindTele l [] = pure l bindTele l ((x, a) : rest) = do v <- fresh (Just x) a.shape From fb8a48762b2facf3dafb17f6f180a2d4948bb2ca Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Mon, 24 Aug 2026 16:55:03 +0100 Subject: [PATCH 11/42] replaced Extern with Param, removed type param --- .../coln-compiler/src/Coln/FLIR/Flatten.hs | 87 ++++++++----------- packages/coln-compiler/src/Coln/FLIR/Value.hs | 33 +++---- 2 files changed, 56 insertions(+), 64 deletions(-) diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index b24586d4..f350e3e1 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -11,37 +11,17 @@ import Control.Monad.State import Data.Set qualified as Set import Data.Vector.Strict qualified as Vec -class Extern e where - eproj :: e -> Name -> e - - -instance Extern Void where - eproj = \case - -data Els e - = Scalar (V.El e) - | Cons (Dict (Els e)) +data Els + = Scalar V.El + | Cons (Dict Els) | Erased -extern :: e -> Els e -extern v = Scalar (V.Extern v) - -getScalar :: Els e -> V.El e -getScalar (Scalar v) = v -getScalar _ = panic "tried to get leaf value of non-leaf" - -asAtomHead :: Els e -> Maybe (V.El e) -asAtomHead (Scalar v) = Just v -asAtomHead Erased = Nothing -asAtomHead _ = panic "tried to get leaf value of non-leaf" - -proj :: Extern e => Els e -> Name -> Els e +proj :: Els -> Name -> Els proj (Cons fields) x = elemAt fields x proj Erased _ = Erased -proj (Scalar (V.Extern v)) x = Scalar (V.Extern (eproj v x)) proj (Scalar _) _ = panic "tried to project from non-extern scalar" -concatEls :: [Els e] -> [V.El e] +concatEls :: [Els] -> [V.El] concatEls vs = toList $ go vs BwdNil where go [] vs' = vs' @@ -49,48 +29,48 @@ concatEls vs = toList $ go vs BwdNil go (Cons d : rest) vs' = go rest (go (toList d.values) vs') go (Erased : rest) vs' = go rest vs' -newtype Props e = Props {apply :: Bwd (V.Prop e) -> Bwd (V.Prop e)} +newtype Props = Props {apply :: Bwd V.Prop -> Bwd V.Prop} -instance Semigroup (Props e) where +instance Semigroup Props where ps0 <> ps1 = Props (ps1.apply . ps0.apply) -instance Monoid (Props e) where +instance Monoid Props where mempty = Props id -instance ToList (Props e) (V.Prop e) where +instance ToList Props V.Prop where toList ps = toList (ps.apply BwdNil) -single :: V.Prop e -> Props e +single :: V.Prop -> Props single p = Props (:> p) -data AuxilaryVars e = AuxilaryVars +data AuxilaryVars = AuxilaryVars { vars :: Bwd (V.ColName, V.ColType) - , props :: Props e - , length :: Int + , numVars :: Int + , props :: Props , usedRoots :: Set.Set Name } -newtype FlatM e a = FlatM {unFlatM :: State (AuxilaryVars e) a} - deriving (Functor, Applicative, Monad, MonadState (AuxilaryVars e)) +newtype FlatM a = FlatM {unFlatM :: State AuxilaryVars a} + deriving (Functor, Applicative, Monad, MonadState AuxilaryVars) -runFlatM :: FlatM e a -> (a, [(V.ColName, V.ColType)], Props e) +runFlatM :: FlatM a -> (a, [(V.ColName, V.ColType)], Props) runFlatM action = do - let (x, aux) = runState action.unFlatM (AuxilaryVars BwdNil mempty 0 Set.empty) + let (x, aux) = runState action.unFlatM (AuxilaryVars BwdNil 0 mempty Set.empty) (x, toList aux.vars, aux.props) -freshAt :: Path -> S.Shape -> FlatM e (Els e) +freshAt :: Path -> S.Shape -> FlatM Els freshAt p = \case S.Scalar t -> do aux <- get - let i = aux.length - put $ aux{vars = (aux.vars :> (p, t)), length = (i + 1)} + let i = aux.numVars + put $ aux{vars = (aux.vars :> (p, t)), numVars = (i + 1)} pure $ Scalar $ V.LocalVar $ FId i S.Tuple fields -> do fields' <- forM (toList fields) $ \(x, sh) -> freshAt (p :> x) sh pure $ Cons $ withHead fields fields' S.Unstored -> pure Erased -fresh :: Maybe Name -> S.Shape -> FlatM e (Els e) +fresh :: Maybe Name -> S.Shape -> FlatM Els fresh mx sh = do x <- case mx of Just x -> pure x @@ -101,19 +81,28 @@ fresh mx sh = do pure x freshAt (BwdNil :> x) sh -type Locals e = Bwd (Els e) +getScalar :: Els -> V.El +getScalar (Scalar v) = v +getScalar _ = panic "tried to get leaf value of non-leaf" + +asAtomHead :: Els -> Maybe V.El +asAtomHead (Scalar v) = Just v +asAtomHead Erased = Nothing +asAtomHead _ = panic "tried to get leaf value of non-leaf" -class Flatten a (b :: Type -> Type) | a -> b where - flatten :: (Extern e) => Locals e -> a -> FlatM e (b e) +type Locals = Bwd Els absName :: S.Abs a -> Maybe Name absName (S.Abs mx _) = mx absName (S.AbsConst _) = Nothing -assert :: Props e -> FlatM e () +assert :: Props -> FlatM () assert ps = modify (\aux -> aux{props = aux.props <> ps}) -app :: (Flatten a b, Extern e) => Locals e -> S.Abs a -> Els e -> FlatM e (b e) +class Flatten a b | a -> b where + flatten :: Locals -> a -> FlatM b + +app :: (Flatten a b) => Locals -> S.Abs a -> Els -> FlatM b app l (S.Abs _ body) v = flatten (l :> v) body app l (S.AbsConst body) _ = flatten l body @@ -133,7 +122,7 @@ instance Flatten (S.El Set) Els where S.Lit l -> pure $ Scalar $ V.Lit l S.Erased -> pure Erased -equate :: (Extern e) => S.Shape -> Els e -> Els e -> Props e +equate :: S.Shape -> Els -> Els -> Props equate (S.Scalar _) v0 v1 = single $ V.PEq (getScalar v0) (getScalar v1) equate (S.Tuple fs) v0 v1 = mconcat [equate t (proj v0 x) (proj v1 x) | (x, t) <- toList fs] @@ -142,7 +131,7 @@ equate S.Unstored _ _ = mempty instance Flatten S.Prop Props where flatten l = \case S.Atom tn t args -> do - mv <- asAtomHead <$> flatten l t + mv <- asAtomHead <$> flatten l t argvs <- traverse (flatten l) args pure $ single $ V.PAtom (V.Atom tn mv (Just <$> concatEls argvs)) S.And ps -> mconcat <$> traverse (flatten l) (toList ps.values) @@ -179,7 +168,7 @@ flattenEntity e = , V.primaryKey = fmap (flattenPrimaryKey (snd <$> e.columns)) e.primaryKey } -bindTele :: (Extern e) => Locals e -> [(Name, S.Query)] -> FlatM e (Locals e) +bindTele :: Locals -> [(Name, S.Query)] -> FlatM Locals bindTele l [] = pure l bindTele l ((x, a) : rest) = do v <- fresh (Just x) a.shape diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs index 0731472e..f1a7392d 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Value.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -34,35 +34,38 @@ data Entity = Entity } deriving (Show, Eq, Generic) --- The type parameter refers to the type of external references In the Realm IR, --- this is Void, but in the FFI which constructs queries dynamically, this is --- host-language expressions. -data El e +-- Param only shows up in queries, not in the FLIR for a realm +data El = Lit Literal | LocalVar FId - | Extern e + | Param FId deriving (Show, Eq, Generic) -data Atom e = Atom +data Atom = Atom { entity :: TableName - , rowId :: Maybe (El e) - , values :: [Maybe (El e)] + , rowId :: Maybe El + , values :: [Maybe El] } -data Prop e - = PAtom (Atom e) - | PEq (El e) (El e) +data Prop + = PAtom Atom + | PEq El El data Rule = Rule { ruleVariant :: SIR.RuleVariant , vars :: [(ColName, ColType)] - , antecedents :: [Prop Void] - , consequents :: [Prop Void] + , antecedents :: [Prop] + , consequents :: [Prop] } data Definition = Definition { vars :: [(ColName, ColType)] - , antecedents :: [Prop Void] + , antecedents :: [Prop] , definand :: TableName - , args :: [El Void] + , args :: [El] + } + +data Query = Query + { vars :: [(ColName, ColType)] + , props :: [Prop] } From f3869dc6a6b27fe658fafde6c12ecf35ea33eec2 Mon Sep 17 00:00:00 2001 From: mvr Date: Tue, 25 Aug 2026 15:39:18 +0100 Subject: [PATCH 12/42] Freshen names in more places --- packages/coln-compiler/src/Coln/Common.hs | 12 ++++++++++++ packages/coln-compiler/src/Coln/FLIR/Flatten.hs | 12 +++++------- packages/coln-compiler/src/Coln/MIR/Layout.hs | 6 +----- packages/coln-compiler/src/Coln/SIR/Cache.hs | 2 +- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index 314c84d4..1db78dfe 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -39,6 +39,7 @@ module Coln.Common ( freshNameFor, freshNamesFor, freshNameWithPref, + freshenFor, Match (..), mangleToDoc, mangleToString, @@ -291,6 +292,9 @@ instance HasNames (Dict a) where instance HasNames [Name] where namesIn xs = Set.fromList xs +instance HasNames (Bwd Name) where + namesIn xs = Set.fromList (toList xs) + instance HasNames (Set.Set Name) where namesIn = id @@ -306,6 +310,14 @@ freshNameWithPref a (Just x) = case Set.member x (namesIn a) of False -> x freshNameWithPref a Nothing = freshNameFor a +freshenBy :: Name -> String -> Name +freshenBy (Name qual last) s = Name (qual ++ [last]) (fromString s) + +freshenFor :: (HasNames a) => a -> Name -> Name +freshenFor a x = head $ filter + (\x -> not $ Set.member x (namesIn a)) + (x : (freshenBy x <$> alphaStrings)) + -- Any -------------------------------------------------------------------------------- diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index f350e3e1..1d5570b7 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -72,13 +72,11 @@ freshAt p = \case fresh :: Maybe Name -> S.Shape -> FlatM Els fresh mx sh = do - x <- case mx of - Just x -> pure x - Nothing -> do - aux <- get - let x = freshNameFor aux.usedRoots - put $ aux{usedRoots = Set.insert x aux.usedRoots} - pure x + aux <- get + let x = case mx of + Just x -> freshenFor aux.usedRoots x + Nothing -> freshNameFor aux.usedRoots + put $ aux{usedRoots = Set.insert x aux.usedRoots} freshAt (BwdNil :> x) sh getScalar :: Els -> V.El diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs index 7fa7553a..22dcb701 100644 --- a/packages/coln-compiler/src/Coln/MIR/Layout.hs +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -5,7 +5,6 @@ module Coln.MIR.Layout where import Data.Set qualified as Set -import Data.String (fromString) import Data.Vector.Strict qualified as Vector import Coln.Common @@ -22,11 +21,8 @@ import Coln.MIR.Value qualified as V -- Layout is the process of creating a realm from a theory, along with the -- universal model of that theory in the realm. -freshenBy :: Name -> String -> Name -freshenBy (Name qual last) s = Name (qual ++ [last]) (fromString s) - argName :: Set.Set Name -> V.Clo a b -> Name -argName _ (V.Clo x _) = x +argName used (V.Clo x _) = freshenFor used x argName used (V.CloConst _) = freshNameFor used data Scope = Scope diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs index 8e8afd7f..cb6b6bd6 100644 --- a/packages/coln-compiler/src/Coln/SIR/Cache.hs +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -23,7 +23,7 @@ bind :: Scope -> Maybe Name -> V.Ty Set -> (Name, V.El Set, Scope) bind sc mx a = do let q = separate sc.len a let x = case mx of - Just x -> x + Just x -> freshenFor sc.used x Nothing -> freshNameFor sc.used let v = V.local (FId sc.len) let sc' = From caa3ddd2ae782794580c20bf33388b099fd7827d Mon Sep 17 00:00:00 2001 From: mvr Date: Tue, 25 Aug 2026 15:39:44 +0100 Subject: [PATCH 13/42] Function `intro` should store domain type not full type --- packages/coln-compiler/src/Coln/Elaborator/Rules/Function.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/coln-compiler/src/Coln/Elaborator/Rules/Function.hs b/packages/coln-compiler/src/Coln/Elaborator/Rules/Function.hs index b73f6e5c..68fef672 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Rules/Function.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Rules/Function.hs @@ -44,7 +44,7 @@ intro sp x body = Chk \e a -> body.elab (e{scope = scope', target = appTarget ft.variant e.target v}) (V.appClo ft.cod v) - pure $ lam ft.variant e.scope.locals (fromVTy e.scope.len a) (S.Abs x ebody) + pure $ lam ft.variant e.scope.locals (fromVTy e.scope.len ft.dom) (S.Abs x ebody) _ -> do let msg = "tried to check a lambda expression at a non-function type" failWith e.diagEnv sp CheckLambdaAtNonFunctionType msg From d6b517925cb7062e606c5c5bb5ba3d457d267bc0 Mon Sep 17 00:00:00 2001 From: mvr Date: Tue, 25 Aug 2026 15:40:22 +0100 Subject: [PATCH 14/42] Make `flattenRule` respect `ctxSide` for the input preconditions --- packages/coln-compiler/src/Coln/FLIR/Flatten.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index 1d5570b7..134e1d52 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -180,11 +180,14 @@ flattenRule r = do ante <- flatten vs r.antecedent cons <- flatten vs r.consequent pure (ante, cons) + let (ruleAnte, ruleCons) = case r.ctxSide of + S.Antecedent -> (ps <> ante, cons) + S.Consequent -> (ante, ps <> cons) V.Rule { V.ruleVariant = r.ruleVariant , V.vars = vars - , V.antecedents = toList (ps <> ante) - , V.consequents = toList cons + , V.antecedents = toList ruleAnte + , V.consequents = toList ruleCons } flattenDefinition :: S.Definition -> V.Definition From f4322147329c0b5febbdd055f1eec264ab7801c3 Mon Sep 17 00:00:00 2001 From: mvr Date: Tue, 25 Aug 2026 15:41:15 +0100 Subject: [PATCH 15/42] Separate `Lookup` args under one more binder --- packages/coln-compiler/src/Coln/SIR/Separate.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs index 7d7a6ffa..85688fc2 100644 --- a/packages/coln-compiler/src/Coln/SIR/Separate.hs +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -17,7 +17,7 @@ instance Separate V.Head (S.El Set) where separate n = \case V.Var (FId i) -> S.Var (BId (n - i - 1)) V.Lookup tn args ret -> do - let args' = separate n <$> args + let args' = separate (n + 1) <$> args let pred = S.Atom tn S.Erased (args' ++ [S.Var 0]) S.Single $ S.Query (shapeOf ret) (S.Abs Nothing pred) From fa09a3e678889ef0727156c757cde3ebf7342792 Mon Sep 17 00:00:00 2001 From: mvr Date: Tue, 25 Aug 2026 15:41:42 +0100 Subject: [PATCH 16/42] Mark `foreignKey` rule as such --- packages/coln-compiler/src/Coln/SIR/Separate.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs index 85688fc2..28368f63 100644 --- a/packages/coln-compiler/src/Coln/SIR/Separate.hs +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -87,7 +87,7 @@ separateGenerator tn = \case let table = Entity Table (zip names ((.shape) <$> septys)) primaryKey let atom = S.Atom tn S.Erased [S.Var (BId (argNum - i - 1)) | i <- [0 .. argNum - 1]] let foreignKey = Rule Enforced Consequent (zip names septys) atom S.trueProp - Realm{entities = Leaf table, definitions = Node $ fromList [], rules = Leaf foreignKey} + Realm{entities = Leaf table, definitions = Node $ fromList [], rules = Node $ fromList [("foreignKey", Leaf foreignKey)]} V.Fun xs tys cod -> case hlevelOf cod of HUnit -> Realm{entities = Node $ fromList [], definitions = Node $ fromList [], rules = Node $ fromList []} HProp -> do From 354ab15709829e0460e4a9e6b3dec4f591d6436b Mon Sep 17 00:00:00 2001 From: mvr Date: Tue, 25 Aug 2026 15:42:12 +0100 Subject: [PATCH 17/42] Give result column a name, fix de Bruijn issue --- packages/coln-compiler/src/Coln/SIR/Separate.hs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs index 28368f63..f05a3691 100644 --- a/packages/coln-compiler/src/Coln/SIR/Separate.hs +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -98,14 +98,24 @@ separateGenerator tn = \case let rule = Rule Monitored Antecedent (zip names septys) S.trueProp codProp Realm{entities = Node $ fromList [], definitions = Node $ fromList [], rules = Leaf rule} HSet -> do - let names = toList xs - let argNum = length names + let argNames = toList xs + let argNum = length argNames + + let tableNameLast = case tn.path of + (_ :> last) -> last + BwdNil -> tn.realm + let resultName = freshenFor xs tableNameLast + let names = argNames ++ [resultName] + let septys = uncurry separate <$> zip [0 ..] (toList (tys :> cod)) let table = Entity Table (zip names ((.shape) <$> septys)) (Just [0 .. argNum - 1]) - let foreignKeyAnte = S.Atom tn S.Erased [S.Var (BId (argNum - i - 1)) | i <- [0 .. argNum]] + + let foreignKeyAnte = S.Atom tn S.Erased [S.Var (BId (argNum - i)) | i <- [0 .. argNum]] let foreignKey = Rule Enforced Consequent (zip names septys) foreignKeyAnte S.trueProp + let totalCons = S.Atom tn S.Erased [S.Var (BId (argNum - i - 1)) | i <- [0 .. argNum - 1]] let total = Rule Monitored Antecedent (zip names (take argNum septys)) S.trueProp totalCons + Realm{entities = Leaf table, definitions = Node $ fromList [], rules = Node $ fromList [("foreignKey", Leaf foreignKey), ("total", Leaf total)]} _ -> panic "bad h-level of cod" From 1598c13ee071c8c7ef3f5a845077c72e987068cb Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Tue, 25 Aug 2026 17:03:28 +0100 Subject: [PATCH 18/42] generate mostly works --- packages/coln-compiler/coln-compiler.cabal | 1 + .../src/Coln/Backend/TypeScript/Generate.hs | 204 ++++++++---------- packages/coln-compiler/src/Coln/Common.hs | 34 ++- packages/coln-compiler/src/Coln/SIR/Realm.hs | 3 + 4 files changed, 128 insertions(+), 114 deletions(-) diff --git a/packages/coln-compiler/coln-compiler.cabal b/packages/coln-compiler/coln-compiler.cabal index 038b5e26..1874c67f 100644 --- a/packages/coln-compiler/coln-compiler.cabal +++ b/packages/coln-compiler/coln-compiler.cabal @@ -104,6 +104,7 @@ library filepath, fnotation, hashable, + keys, mtl, ordered-containers, prettyprinter, diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs index ca4487dc..ca9bd332 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs @@ -4,31 +4,31 @@ module Coln.Backend.TypeScript.Generate where --- import Control.Monad (forM_) + import Control.Monad.State -- import Data.Aeson qualified as AE --- import Data.Foldable (foldlM) +import Data.Foldable (foldlM) -- import Data.Foldable qualified as F -- import Data.Map.Ordered qualified as OMap import Data.Set qualified as Set import Data.String (IsString (..)) --- import Data.Text.Lazy qualified as TL --- import Data.Text.Lazy.IO qualified as TLIO +import Data.Text.Lazy qualified as TL +import Data.Text.Lazy.IO qualified as TLIO import Prettyprinter --- import Prettyprinter.Render.Text --- import System.FilePath +import Prettyprinter.Render.Text +import System.FilePath import Coln.Backend.TypeScript.AST qualified as TS --- import Coln.Backend.TypeScript.Assemble (asm) +import Coln.Backend.TypeScript.Assemble (asm) import Coln.Backend.TypeScript.Params import Coln.Common --- import Coln.Core.Globals import Coln.Core.Params import Coln.Core.Readback import Coln.Core.Value qualified as V import Coln.Core.Syntax qualified as S import Coln.SIR.Syntax qualified as SIR +import Coln.SIR.Realm qualified as SIR import Coln.FLIR.Flatten qualified as FLIR import Coln.FLIR.Value qualified as FLIR @@ -124,79 +124,59 @@ genEntryModule imports a ev = go 0 a ev go (n + 1) (V.appClo ft.cod v) (V.ebind (flip (V.app ft.variant) v) ev') go _ _ _ = Nothing +tableNameDoc :: TableName -> DDoc +tableNameDoc tn = concatWith (surround dot) (dpretty <$> (tn.realm : toList tn.path)) + +data FlatParams = FlatParams + { paramVals :: Bwd TS.El + , numParams :: Int + } + +allocParams :: TS.El -> SIR.Shape -> State FlatParams FLIR.Els +allocParams v = \case + SIR.Tuple d -> do + FLIR.Cons <$> mapWithKeyM (\x sh -> allocParams (TS.Proj v (mangle x)) sh) d + SIR.Scalar _ -> state \p -> + ( FLIR.Scalar (FLIR.Param (FId p.numParams)) + , p { paramVals = p.paramVals :> v, numParams = p.numParams + 1 } + ) + SIR.Unstored -> pure FLIR.Erased + data TSEnv = TSEnv - { locals :: Bwd TS.El + { tsLocals :: Bwd TS.El , usedNames :: Set.Set Name + , flatParams :: FlatParams + , flirLocals :: FLIR.Locals } -instance FLIR.Extern TS.El where - eproj v x = TS.Proj v (mangle x) - -tableNameDoc :: TableName -> DDoc -tableNameDoc tn = concatWith (surround dot) (dpretty <$> (tn.realm : toList tn.path)) +emptyTSEnv :: TSEnv +emptyTSEnv = TSEnv BwdNil Set.empty (FlatParams BwdNil 0) BwdNil -tagged :: DDoc -> TS.El -> TS.El -tagged x v = TS.Object [("tag", TS.String x), ("value", v)] - -stageEl :: FLIR.El TS.El -> TS.El -stageEl = \case - FLIR.Lit l -> tagged "Lit" $ TS.Lit l - FLIR.LocalVar (FId i) -> tagged "LocalVar" $ TS.Lit $ LitInt i - FLIR.Extern v -> v - -orNull :: (a -> TS.El) -> Maybe a -> TS.El -orNull f (Just x) = f x -orNull _ Nothing = TS.Null - -stageAtom :: FLIR.Atom TS.El -> TS.El -stageAtom a = TS.Object - [ ("entity", TS.String $ tableNameDoc a.entity) - , ("rowId", orNull stageEl a.rowId) - , ("values", TS.List (orNull stageEl <$> a.values)) - ] - -stageProp :: FLIR.Prop TS.El -> TS.El -stageProp = \case - FLIR.PAtom a -> tagged "PAtom" $ stageAtom a - FLIR.PEq v0 v1 -> tagged "PEq" $ TS.Object [("lhs", stageEl v0), ("rhs", stageEl v1)] - -builtinDoc :: BuiltinTy -> DDoc -builtinDoc = \case - BuiltinInt -> "Int" - BuiltinString -> "String" - -genColType :: FLIR.ColType -> TS.El -genColType = \case - SIR.RowId x -> tagged "RowId" $ TS.String $ tableNameDoc x - SIR.BuiltinTy ty -> tagged "BuiltinTy" $ TS.String $ builtinDoc ty - -reconstructEl :: FLIR.El TS.El -> TS.El -reconstructEl = \case +reconstructEl :: FlatParams -> FLIR.El -> TS.El +reconstructEl e = \case FLIR.LocalVar (FId i) -> TS.Index (TS.Var "result") i FLIR.Lit l -> TS.Lit l - FLIR.Extern x -> x + FLIR.Param (FId i) -> elemAt e.paramVals (BId (e.numParams - i - 1)) -reconstructEls :: FLIR.Els TS.El -> TS.El -reconstructEls = \case - FLIR.Scalar v -> reconstructEl v - FLIR.Cons d -> TS.Object [(mangle x, reconstructEls t) | (x, t) <- toList d] +reconstructEls :: FlatParams -> FLIR.Els -> TS.El +reconstructEls e = \case + FLIR.Scalar v -> reconstructEl e v + FLIR.Cons d -> TS.Object [(mangle x, reconstructEls e t) | (x, t) <- toList d] FLIR.Erased -> TS.Null genQuery :: Access -> TSEnv -> SIR.Query -> TS.El genQuery _access e q = do - let ((v, mainprops), vars, auxprops) = FLIR.runFlatM $ do + let ((v, mainProps), vars, auxProps) = FLIR.runFlatM $ do v <- FLIR.freshAt (BwdNil :> "result") q.shape - mainprops <- FLIR.app (FLIR.extern <$> e.locals) q.pred v + mainprops <- FLIR.app e.flirLocals q.pred v pure (v, mainprops) - let flir = TS.Object - [ ("vars", TS.List $ genColType . snd <$> vars) - , ("props", TS.List $ stageProp <$> toList (mainprops <> auxprops)) - ] + let query = FLIR.Query vars (toList (mainProps <> auxProps)) + let flir = TS.String (undefined query) -- TODO: should make sure "result" is fresh let reconstruct = TS.Lam (TS.Binding "result" (TS.ListTy (TS.runtime Value))) - (TS.Block [] (Just (reconstructEls v))) + (TS.Block [] (Just (reconstructEls e.flatParams v))) TS.New (TS.Const (TS.runtime Query)) [flir, reconstruct] varName :: SIR.Abs a -> Set.Set Name -> Name @@ -209,7 +189,7 @@ genAbs :: Access -> TSEnv -> SIR.Abs (SIR.El l) -> (Name, TS.El) genAbs access e (SIR.Abs mx body) = do let x = freshNameWithPref e.usedNames mx let e' = e - { locals = e.locals :> TS.Var (mangle x) + { tsLocals = e.tsLocals :> TS.Var (mangle x) , usedNames = Set.insert x e.usedNames } (x, genEl access e' body) @@ -221,7 +201,7 @@ genAbs access e (SIR.AbsConst body) = do genEl :: Access -> TSEnv -> SIR.El l -> TS.El genEl access e = \case SIR.LiftEl t -> genEl access e t - SIR.Var i -> elemAt e.locals i + SIR.Var i -> elemAt e.tsLocals i SIR.Single q -> TS.MethodCall (genQuery access e q) "single" [] SIR.Proj t x -> TS.Proj (genEl access e t) (mangle x) SIR.Multi _ q -> TS.MethodCall (genQuery access e q) "multi" [] @@ -235,53 +215,53 @@ genEl access e = \case SIR.Lit l -> TS.Lit l SIR.Erased -> TS.Null --- genRealmConstructor :: Access -> Realm -> TS.Constructor --- genRealmConstructor access r = do --- let args = case access of --- View -> --- [ TS.Binding "store" (TS.runtime StoreHandle) --- ] --- Transaction -> --- [ TS.Binding "store" (TS.runtime StoreHandle) --- , TS.Binding "transaction" (TS.runtime TransactionHandle) --- ] --- let superCall = case extends access of --- Just _ -> [TS.Expr (TS.Call (TS.Var "super") [TS.Var "store"])] --- Nothing -> [] --- let body = --- TS.Block --- (superCall ++ [TS.Assign (TS.QId ["this"] "root") (genEl access emptyTSCtxShape r.root)]) --- Nothing --- TS.Constructor args body - --- genRealmClass :: Access -> Realm -> TS.Class --- genRealmClass access r = --- TS.Class --- (fromShow access) --- Nothing --- (fromShow <$> extends access) --- [TS.Binding "root" (genTy access 0 r.rootType)] --- (genRealmConstructor access r) - --- genRealmModule :: [TS.Import] -> Realm -> TS.Module --- genRealmModule imports r = do --- let classes = for accessLevels $ \access -> TS.DClass $ genRealmClass access r --- TS.Module imports (TS.Exported <$> classes) - --- render :: DDoc -> TL.Text --- render = renderLazy . layoutPretty defaultLayoutOptions - --- writeModule :: FilePath -> Name -> TS.Module -> IO () --- writeModule outdir x mod = do --- let fn = outdir TS.idToString (mangle x) <> ".ts" --- let content = render $ asm mod --- TLIO.writeFile fn content - --- runtimeImport :: TS.Import --- runtimeImport = TS.ImportQualified "runtime" "@coln-project/runtime" - --- forAccM :: (Monad m) => [b] -> a -> (a -> b -> m a) -> m a --- forAccM bs init f = foldlM f init bs +genRealmConstructor :: Access -> SIR.Realm -> TS.Constructor +genRealmConstructor access r = do + let args = case access of + View -> + [ TS.Binding "store" (TS.runtime StoreHandle) + ] + Transaction -> + [ TS.Binding "store" (TS.runtime StoreHandle) + , TS.Binding "transaction" (TS.runtime TransactionHandle) + ] + let superCall = case extends access of + Just _ -> [TS.Expr (TS.Call (TS.Var "super") [TS.Var "store"])] + Nothing -> [] + let body = + TS.Block + (superCall ++ [TS.Assign (TS.QId ["this"] "root") (genEl access emptyTSEnv r.root)]) + Nothing + TS.Constructor args body + +genRealmClass :: Access -> SIR.Realm -> TS.Class +genRealmClass access r = + TS.Class + (fromShow access) + Nothing + (fromShow <$> extends access) + [TS.Binding "root" (genTy access 0 r.rootType)] + (genRealmConstructor access r) + +genRealmModule :: [TS.Import] -> SIR.Realm -> TS.Module +genRealmModule imports r = do + let classes = for accessLevels $ \access -> TS.DClass $ genRealmClass access r + TS.Module imports (TS.Exported <$> classes) + +render :: DDoc -> TL.Text +render = renderLazy . layoutPretty defaultLayoutOptions + +writeModule :: FilePath -> Name -> TS.Module -> IO () +writeModule outdir x mod = do + let fn = outdir TS.idToString (mangle x) <> ".ts" + let content = render $ asm mod + TLIO.writeFile fn content + +runtimeImport :: TS.Import +runtimeImport = TS.ImportQualified "runtime" "@coln-project/runtime" + +forAccM :: (Monad m) => [b] -> a -> (a -> b -> m a) -> m a +forAccM bs init f = foldlM f init bs -- generate :: Globals -> FilePath -> IO () -- generate ge outdir = do diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index 1db78dfe..5595ee75 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -5,9 +5,10 @@ module Coln.Common ( module Diagnostician, module FNotation, + module Data.Key, + module Data.Kind, module Data.Map, module Data.Map.Ordered, - module Data.Kind, module Data.Vector.Strict, module Data.Void, module Data.Text, @@ -50,6 +51,7 @@ where import Coln.Report import Data.Foldable qualified as F +import Data.Key (TraversableWithKey (..), Keyed (..), FoldableWithKey (..), Key) import Data.Kind (Constraint, Type) import Data.Map (Map) import Data.Map qualified as Map @@ -61,7 +63,10 @@ import Data.Text (Text) import Data.Traversable hiding (for) import Data.Vector.Strict (Vector) import Data.Vector.Strict qualified as V +import Data.Vector.Generic (stream, unstreamM) +import Data.Vector.Fusion.Bundle qualified as Bundle import Data.Void + import Diagnostician import FNotation (Name (..)) import Prettyprinter (Pretty (..), defaultLayoutOptions, layoutPretty, (<+>)) @@ -252,7 +257,32 @@ getKeyIndex :: Dict a -> Name -> KeyIndex getKeyIndex d x = KeyIndex $ d.head.byName Map.! x withHead :: Dict a -> [b] -> Dict b -withHead d xs = Dict d.head (V.fromList xs) +withHead d xs = do + let n = V.length d.values + Dict d.head (V.fromListN n xs) + +dstream :: Dict a -> Bundle.Bundle V.Vector (Name, a) +dstream d = Bundle.zip (stream d.head.keys) (stream d.values) + +type instance Key Dict = Name + +instance Keyed Dict where + mapWithKey f d = Dict d.head $ V.zipWith f d.head.keys d.values + +instance FoldableWithKey Dict where + toKeyedList = toList + foldMapWithKey f = foldlWithKey (\acc x v -> acc <> f x v) mempty + foldrWithKey f init = + Bundle.foldr (uncurry f) init . dstream + foldlWithKey f init = + Bundle.foldl (\acc (x, v) -> f acc x v) init . dstream + +instance TraversableWithKey Dict where + traverseWithKey f d = withHead d <$> + traverse (uncurry f) (zip (toList d.head.keys) (toList d.values)) + mapWithKeyM f d = Dict d.head <$> + (unstreamM $ Bundle.mapM (uncurry f) $ dstream d) + -- Name-based Tries -------------------------------------------------------------------------------- diff --git a/packages/coln-compiler/src/Coln/SIR/Realm.hs b/packages/coln-compiler/src/Coln/SIR/Realm.hs index 751d0799..21a23cf7 100644 --- a/packages/coln-compiler/src/Coln/SIR/Realm.hs +++ b/packages/coln-compiler/src/Coln/SIR/Realm.hs @@ -3,6 +3,7 @@ module Coln.SIR.Realm where import Coln.Common import Coln.Core.Params import Coln.SIR.Syntax +import Coln.Core.Value qualified as CoreV data EntityVariant = Table @@ -36,4 +37,6 @@ data Realm = Realm { entities :: Trie Entity , definitions :: Trie Definition , rules :: Trie Rule + , root :: El Theory + , rootType :: CoreV.Ty N } From e901ba35a9905e93a8918be60cf7624fc84595d3 Mon Sep 17 00:00:00 2001 From: James Deikun Date: Fri, 28 Aug 2026 12:25:44 -0400 Subject: [PATCH 19/42] FLIR generation and output plus format pass --- packages/coln-compiler/coln-compiler.cabal | 6 +- .../src/Coln/Backend/TypeScript/Generate.hs | 26 ++--- packages/coln-compiler/src/Coln/Common.hs | 25 +++-- .../coln-compiler/src/Coln/Core/Evaluation.hs | 2 +- .../src/Coln/Elaborator/Rules/Record.hs | 2 +- .../coln-compiler/src/Coln/FLIR/Flatten.hs | 2 +- packages/coln-compiler/src/Coln/FLIR/Top.hs | 24 +++++ packages/coln-compiler/src/Coln/FLIR/Value.hs | 101 ++++++++++++++++++ .../coln-compiler/src/Coln/MIR/Interpret.hs | 10 ++ packages/coln-compiler/src/Coln/MIR/Layout.hs | 2 +- .../coln-compiler/src/Coln/MIR/Readback.hs | 9 +- packages/coln-compiler/src/Coln/MIR/Realm.hs | 3 +- packages/coln-compiler/src/Coln/MIR/Top.hs | 42 ++++++++ packages/coln-compiler/src/Coln/SIR/Cache.hs | 39 +++++-- packages/coln-compiler/src/Coln/SIR/Realm.hs | 12 ++- .../coln-compiler/src/Coln/SIR/Separate.hs | 10 +- packages/coln-compiler/src/Coln/SIR/Syntax.hs | 35 ++++++ packages/coln-compiler/src/Coln/SIR/Top.hs | 57 ++++++++++ packages/coln-compiler/src/Coln/Top.hs | 64 +++++++++++ packages/coln-compiler/test/Main.hs | 2 +- 20 files changed, 426 insertions(+), 47 deletions(-) create mode 100644 packages/coln-compiler/src/Coln/FLIR/Top.hs create mode 100644 packages/coln-compiler/src/Coln/MIR/Top.hs create mode 100644 packages/coln-compiler/src/Coln/SIR/Top.hs create mode 100644 packages/coln-compiler/src/Coln/Top.hs diff --git a/packages/coln-compiler/coln-compiler.cabal b/packages/coln-compiler/coln-compiler.cabal index 1874c67f..a3a0f90d 100644 --- a/packages/coln-compiler/coln-compiler.cabal +++ b/packages/coln-compiler/coln-compiler.cabal @@ -40,6 +40,7 @@ library Coln.Elaborator.Rules.Universe Coln.Elaborator.Rules.Variable Coln.FLIR.Flatten + Coln.FLIR.Top Coln.FLIR.Value Coln.Frontend.Diagnostics Coln.Frontend.Notation @@ -54,12 +55,15 @@ library Coln.MIR.Readback Coln.MIR.Realm Coln.MIR.Syntax + Coln.MIR.Top Coln.MIR.Value Coln.Report Coln.SIR.Cache Coln.SIR.Realm Coln.SIR.Separate Coln.SIR.Syntax + Coln.SIR.Top + Coln.Top hs-source-dirs: src default-language: GHC2024 @@ -155,7 +159,7 @@ test-suite coln-compiler-test fnotation, ordered-containers, prettyprinter, - tasty, + tasty ^>=1.5.4, tasty-expected-failure, tasty-golden, tasty-hunit, diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs index ca9bd332..f2f46598 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs @@ -4,10 +4,11 @@ module Coln.Backend.TypeScript.Generate where - import Control.Monad.State + -- import Data.Aeson qualified as AE import Data.Foldable (foldlM) + -- import Data.Foldable qualified as F -- import Data.Map.Ordered qualified as OMap import Data.Set qualified as Set @@ -25,12 +26,12 @@ import Coln.Common import Coln.Core.Params import Coln.Core.Readback -import Coln.Core.Value qualified as V import Coln.Core.Syntax qualified as S -import Coln.SIR.Syntax qualified as SIR -import Coln.SIR.Realm qualified as SIR +import Coln.Core.Value qualified as V import Coln.FLIR.Flatten qualified as FLIR import Coln.FLIR.Value qualified as FLIR +import Coln.SIR.Realm qualified as SIR +import Coln.SIR.Syntax qualified as SIR mangle :: Name -> TS.Id mangle = TS.Id . mangleToDoc @@ -67,11 +68,11 @@ genInterface access n = \case class TrackGlobals a where trackGlobals :: a -> State (Set.Set Name) () -instance TrackGlobals (f c) => TrackGlobals (S.Abs f c) where +instance (TrackGlobals (f c)) => TrackGlobals (S.Abs f c) where trackGlobals (S.Abs _ body) = trackGlobals body trackGlobals (S.AbsConst body) = trackGlobals body -instance TrackGlobals a => TrackGlobals (Name, a) where +instance (TrackGlobals a) => TrackGlobals (Name, a) where trackGlobals (_, t) = trackGlobals t instance TrackGlobals (S.El c) where @@ -138,7 +139,7 @@ allocParams v = \case FLIR.Cons <$> mapWithKeyM (\x sh -> allocParams (TS.Proj v (mangle x)) sh) d SIR.Scalar _ -> state \p -> ( FLIR.Scalar (FLIR.Param (FId p.numParams)) - , p { paramVals = p.paramVals :> v, numParams = p.numParams + 1 } + , p{paramVals = p.paramVals :> v, numParams = p.numParams + 1} ) SIR.Unstored -> pure FLIR.Erased @@ -188,14 +189,15 @@ varName _ xs = freshNameFor xs genAbs :: Access -> TSEnv -> SIR.Abs (SIR.El l) -> (Name, TS.El) genAbs access e (SIR.Abs mx body) = do let x = freshNameWithPref e.usedNames mx - let e' = e - { tsLocals = e.tsLocals :> TS.Var (mangle x) - , usedNames = Set.insert x e.usedNames - } + let e' = + e + { tsLocals = e.tsLocals :> TS.Var (mangle x) + , usedNames = Set.insert x e.usedNames + } (x, genEl access e' body) genAbs access e (SIR.AbsConst body) = do let x = freshNameFor e.usedNames - let e' = e { usedNames = Set.insert x e.usedNames } + let e' = e{usedNames = Set.insert x e.usedNames} (x, genEl access e' body) genEl :: Access -> TSEnv -> SIR.El l -> TS.El diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index 5595ee75..def5445e 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -51,7 +51,7 @@ where import Coln.Report import Data.Foldable qualified as F -import Data.Key (TraversableWithKey (..), Keyed (..), FoldableWithKey (..), Key) +import Data.Key (FoldableWithKey (..), Key, Keyed (..), TraversableWithKey (..)) import Data.Kind (Constraint, Type) import Data.Map (Map) import Data.Map qualified as Map @@ -61,10 +61,10 @@ import Data.Set qualified as Set import Data.String (IsString, fromString) import Data.Text (Text) import Data.Traversable hiding (for) +import Data.Vector.Fusion.Bundle qualified as Bundle +import Data.Vector.Generic (stream, unstreamM) import Data.Vector.Strict (Vector) import Data.Vector.Strict qualified as V -import Data.Vector.Generic (stream, unstreamM) -import Data.Vector.Fusion.Bundle qualified as Bundle import Data.Void import Diagnostician @@ -278,11 +278,12 @@ instance FoldableWithKey Dict where Bundle.foldl (\acc (x, v) -> f acc x v) init . dstream instance TraversableWithKey Dict where - traverseWithKey f d = withHead d <$> - traverse (uncurry f) (zip (toList d.head.keys) (toList d.values)) - mapWithKeyM f d = Dict d.head <$> - (unstreamM $ Bundle.mapM (uncurry f) $ dstream d) - + traverseWithKey f d = + withHead d + <$> traverse (uncurry f) (zip (toList d.head.keys) (toList d.values)) + mapWithKeyM f d = + Dict d.head + <$> (unstreamM $ Bundle.mapM (uncurry f) $ dstream d) -- Name-based Tries -------------------------------------------------------------------------------- @@ -344,9 +345,11 @@ freshenBy :: Name -> String -> Name freshenBy (Name qual last) s = Name (qual ++ [last]) (fromString s) freshenFor :: (HasNames a) => a -> Name -> Name -freshenFor a x = head $ filter - (\x -> not $ Set.member x (namesIn a)) - (x : (freshenBy x <$> alphaStrings)) +freshenFor a x = + head $ + filter + (\x -> not $ Set.member x (namesIn a)) + (x : (freshenBy x <$> alphaStrings)) -- Any -------------------------------------------------------------------------------- diff --git a/packages/coln-compiler/src/Coln/Core/Evaluation.hs b/packages/coln-compiler/src/Coln/Core/Evaluation.hs index 335ef15a..4b777e62 100644 --- a/packages/coln-compiler/src/Coln/Core/Evaluation.hs +++ b/packages/coln-compiler/src/Coln/Core/Evaluation.hs @@ -72,7 +72,7 @@ compileEqualityType eq = do instance Compile S.Ty V.Ty where compile = \case S.U u -> const $ V.U u - S.Decode u t -> do + S.Decode _ t -> do let k = compile t V.ebind V.decode . k S.Function ft -> V.Function . compileFunctionType ft diff --git a/packages/coln-compiler/src/Coln/Elaborator/Rules/Record.hs b/packages/coln-compiler/src/Coln/Elaborator/Rules/Record.hs index bc2b7e69..ea03cd4d 100644 --- a/packages/coln-compiler/src/Coln/Elaborator/Rules/Record.hs +++ b/packages/coln-compiler/src/Coln/Elaborator/Rules/Record.hs @@ -40,7 +40,7 @@ data FieldSetting c = FieldSetting intro :: (V.HasEvaluation c) => Span -> [FieldSetting c] -> Chk c intro @c sp fieldSettings = Chk \e a -> do let go :: Level -> V.Locals -> [(FieldSetting c, (Name, V.Locals -> V.Ty N))] -> IO [(Name, El c)] - go lvl _ [] = pure [] + go _ _ [] = pure [] go lvl vs ((fs, (x, fieldTyC)) : rest) | fs.name == x = do let fieldTy = fieldTyC vs diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index 134e1d52..5ed22d87 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -129,7 +129,7 @@ equate S.Unstored _ _ = mempty instance Flatten S.Prop Props where flatten l = \case S.Atom tn t args -> do - mv <- asAtomHead <$> flatten l t + mv <- asAtomHead <$> flatten l t argvs <- traverse (flatten l) args pure $ single $ V.PAtom (V.Atom tn mv (Just <$> concatEls argvs)) S.And ps -> mconcat <$> traverse (flatten l) (toList ps.values) diff --git a/packages/coln-compiler/src/Coln/FLIR/Top.hs b/packages/coln-compiler/src/Coln/FLIR/Top.hs new file mode 100644 index 00000000..3c8742c0 --- /dev/null +++ b/packages/coln-compiler/src/Coln/FLIR/Top.hs @@ -0,0 +1,24 @@ +-- SPDX-FileCopyrightText: 2026 Coln contributors +-- +-- SPDX-License-Identifier: Apache-2.0 OR MIT + +module Coln.FLIR.Top where + +import Coln.Common +import Coln.Core.Params +import Coln.FLIR.Flatten +import Coln.FLIR.Value qualified as FLIR +import Coln.SIR.Realm qualified as SIR + +import Data.Map.Ordered qualified as OMap + +trieToOMap :: RealmId -> Trie a -> OMap TableName a +trieToOMap rId t = OMap.fromList [(TableName rId k, v) | (k, v) <- toList t] + +sirToFLIR :: RealmId -> SIR.Realm -> FLIR.Realm +sirToFLIR rId r = + FLIR.Realm + { entities = trieToOMap rId $ fmap flattenEntity r.entities + , definitions = trieToOMap rId $ fmap flattenDefinition r.definitions + , rules = trieToOMap rId $ fmap flattenRule r.rules + } diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs index f1a7392d..122e18bc 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Value.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -5,6 +5,13 @@ import Coln.Core.Params import Coln.SIR.Realm qualified as SIR import Coln.SIR.Syntax qualified as SIR +import Control.Arrow ((***)) +import Data.Aeson qualified as AE +import Data.Aeson.Encoding qualified as AE +import Data.Char (toLower) +import Data.Map.Ordered qualified as OMap +import Data.Maybe (fromMaybe) +import Data.Set qualified as Set import GHC.Generics type ColName = Path @@ -46,10 +53,12 @@ data Atom = Atom , rowId :: Maybe El , values :: [Maybe El] } + deriving (Show, Eq, Generic) data Prop = PAtom Atom | PEq El El + deriving (Show, Eq, Generic) data Rule = Rule { ruleVariant :: SIR.RuleVariant @@ -69,3 +78,95 @@ data Query = Query { vars :: [(ColName, ColType)] , props :: [Prop] } + +data Realm = Realm + { entities :: OMap TableName Entity + , definitions :: OMap TableName Definition + , rules :: OMap TableName Rule + } + +-- JSON +-------------------------------------------------------------------------------- + +aeOptions :: AE.Options +aeOptions = + AE.defaultOptions + { AE.allNullaryToStringTag = False + , AE.constructorTagModifier = \x -> fmap toLower (take 1 x) ++ (drop 1 x) + } + +pathMapEncoding :: (SIR.PathLike k) => (a -> AE.Encoding) -> OMap k a -> AE.Encoding +pathMapEncoding f = AE.list (\(k, v) -> AE.pairs $ AE.pair "path" (SIR.encPath k) <> AE.pair "value" (f v)) . OMap.assocs + +instance AE.ToJSON Materialization where + toEncoding = AE.genericToEncoding aeOptions{AE.allNullaryToStringTag = True} + +instance AE.ToJSON IndexMethod where + toEncoding = AE.genericToEncoding aeOptions{AE.allNullaryToStringTag = True} + +instance AE.ToJSON EntityVariant where + toJSON = panic "aesons behaving badly" + toEncoding = \case + Table -> SIR.taggedEncoding "table" $ mempty + View m -> SIR.taggedEncoding "view" $ AE.pair "materialization" $ AE.toEncoding m + Index m cs -> SIR.taggedEncoding "index" $ AE.pair "method" (AE.toEncoding m) <> AE.pair "columns" (AE.list SIR.encPath cs) + +instance AE.ToJSON Entity where + toJSON = panic "aesons behaving badly" + toEncoding e = + AE.pairs $ + mconcat + [ AE.pair "entityVariant" $ AE.toEncoding e.entityVariant + , AE.pair "columns" $ AE.list (\(k, v) -> AE.pairs $ AE.pair "path" (SIR.encPath k) <> AE.pair "type" (AE.toEncoding v)) e.columns + , AE.pair "primaryKey" $ fromMaybe AE.null_ $ fmap (AE.list AE.toEncoding) e.primaryKey + ] + +instance AE.ToJSON El where + toJSON = panic "aesons behaving badly" + toEncoding = \case + Lit l -> SIR.taggedEncoding "lit" $ AE.pair "lit" $ case l of + LitInt i -> SIR.taggedEncoding "int" $ AE.pair "value" $ AE.toEncoding i + LitString s -> SIR.taggedEncoding "string" $ AE.pair "value" $ AE.toEncoding s + LocalVar (FId i) -> SIR.taggedEncoding "var" $ AE.pair "index" $ AE.toEncoding i + Param (FId i) -> SIR.taggedEncoding "param" $ AE.pair "index" $ AE.toEncoding i + +instance AE.ToJSON Atom where + toJSON = panic "aesons behaving badly" + toEncoding a = + AE.pairs $ + mconcat + [ AE.pair "entity" $ SIR.encPath a.entity + , AE.pair "rowId" $ AE.toEncoding a.rowId + , AE.pair "values" $ AE.toEncoding a.values + ] + +instance AE.ToJSON Prop where + toEncoding = \case + PAtom a -> SIR.taggedEncoding "atom" $ AE.pair "atom" $ AE.toEncoding a + PEq l r -> SIR.taggedEncoding "eq" $ AE.pair "left" (AE.toEncoding l) <> AE.pair "right" (AE.toEncoding r) + +instance AE.ToJSON Definition where + toJSON = panic "aesons behaving badly" + toEncoding r = + AE.pairs $ + mconcat + [ AE.pair "vars" $ AE.list (AE.list id . (\(x, y) -> [x, y]) . (SIR.encPath *** AE.toEncoding)) $ r.vars + , AE.pair "antecedents" $ AE.toEncoding r.antecedents + , AE.pair "definand" $ SIR.encPath r.definand + , AE.pair "antecedents" $ AE.toEncoding r.args + ] + +instance AE.ToJSON Rule where + toJSON = panic "aesons behaving badly" + toEncoding r = + AE.pairs $ + mconcat + [ AE.pair "ruleVariant" $ AE.toEncoding r.ruleVariant + , AE.pair "vars" $ AE.list (AE.list id . (\(x, y) -> [x, y]) . (SIR.encPath *** AE.toEncoding)) $ r.vars + , AE.pair "antecedents" $ AE.toEncoding r.antecedents + , AE.pair "consequents" $ AE.toEncoding r.consequents + ] + +instance AE.ToJSON Realm where + toJSON = panic "aesons behaving badly" + toEncoding r = AE.pairs $ AE.pair "entities" (pathMapEncoding AE.toEncoding r.entities) <> AE.pair "definitions" (pathMapEncoding AE.toEncoding r.definitions) <> AE.pair "rules" (pathMapEncoding AE.toEncoding r.rules) diff --git a/packages/coln-compiler/src/Coln/MIR/Interpret.hs b/packages/coln-compiler/src/Coln/MIR/Interpret.hs index 52348657..1d612821 100644 --- a/packages/coln-compiler/src/Coln/MIR/Interpret.hs +++ b/packages/coln-compiler/src/Coln/MIR/Interpret.hs @@ -1,8 +1,12 @@ module Coln.MIR.Interpret where -- Interpret Core syntax into MIR values +import Data.Map.Ordered qualified as OMap + import Coln.Common +import Coln.Core.Globals qualified as S +import Coln.Core.Memoed qualified as M import Coln.Core.Params import Coln.Core.Syntax qualified as S import Coln.MIR.Params @@ -65,3 +69,9 @@ instance Interp (S.Ty c) V.Ty where S.BuiltinTy t -> do Pair SSet $ V.BuiltinTy t S.IsTy t -> interp g e t + +interpGlobals :: S.Globals -> V.Globals +interpGlobals g = foldl go OMap.empty $ OMap.assocs g.definitions + where + go :: V.Globals -> (Name, S.Definition Global) -> V.Globals + go acc (x, def) = acc OMap.>| (x, interp acc BwdNil def.body.stx) diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs index 22dcb701..fd4977aa 100644 --- a/packages/coln-compiler/src/Coln/MIR/Layout.hs +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -81,4 +81,4 @@ layout p sc = \case (gt, M.cons (Dict rt.fieldTypes.head (Vector.fromList ms))) layoutTop :: RealmId -> V.Ty Theory -> (Trie Generator, M.El Theory) -layoutTop x = layout BwdNil (emptyScope x) +layoutTop x = layout (BwdNil :> "root") (emptyScope x) diff --git a/packages/coln-compiler/src/Coln/MIR/Readback.hs b/packages/coln-compiler/src/Coln/MIR/Readback.hs index 88224e7d..701ce77b 100644 --- a/packages/coln-compiler/src/Coln/MIR/Readback.hs +++ b/packages/coln-compiler/src/Coln/MIR/Readback.hs @@ -6,6 +6,8 @@ import Coln.MIR.Params import Coln.MIR.Syntax qualified as S import Coln.MIR.Value qualified as V +import Data.Traversable (mapAccumL) + type CtxLen = Int class Readback a b | a -> b where @@ -46,7 +48,12 @@ instance Readback (V.Ty Theory) (S.Ty Theory) where V.LiftTy LSetTheory a -> S.LiftTy (readb n a) V.U SPropU -> S.U SPropU V.U SSetU -> S.U SSetU - V.Function ft -> undefined + V.Function ft -> case ft.variant.mlevel of + SSetTheory -> S.Function (S.FunctionType ft.variant (readb n ft.dom) (readbClo n ft.cod)) + V.Record rt -> S.Record (S.RecordType rt.hlevel (readbTele n rt.capture rt.fieldTypes)) + +readbTele :: (Traversable f, Readback a b) => CtxLen -> V.Locals -> f (V.Locals -> a) -> f b +readbTele n l = snd . mapAccumL (\(n', l') k -> ((n' + 1, l' :> Pair SSet (V.local (FId n'))), readb n' $ k l')) (n, l) readbClo :: (Readback a b) => CtxLen -> V.Clo (V.El Set) a -> S.Abs b readbClo n (V.Clo x f) = S.Abs x (readb (n + 1) (f (fresh n))) diff --git a/packages/coln-compiler/src/Coln/MIR/Realm.hs b/packages/coln-compiler/src/Coln/MIR/Realm.hs index 29c3c1bb..7e0c1e96 100644 --- a/packages/coln-compiler/src/Coln/MIR/Realm.hs +++ b/packages/coln-compiler/src/Coln/MIR/Realm.hs @@ -2,6 +2,7 @@ module Coln.MIR.Realm where import Coln.Common import Coln.Core.Params +import Coln.Core.Value qualified as CoreV import Coln.MIR.Memoed qualified as M import Coln.MIR.Params import Coln.MIR.Value qualified as V @@ -17,7 +18,7 @@ data RealmDefinition = RealmDefinition data Realm = Realm { root :: V.El Theory - , rootType :: V.Ty Theory + , rootType :: CoreV.Ty N , generators :: Trie Generator , realmDefinitions :: OMap Name RealmDefinition } diff --git a/packages/coln-compiler/src/Coln/MIR/Top.hs b/packages/coln-compiler/src/Coln/MIR/Top.hs new file mode 100644 index 00000000..28d403ec --- /dev/null +++ b/packages/coln-compiler/src/Coln/MIR/Top.hs @@ -0,0 +1,42 @@ +-- SPDX-FileCopyrightText: 2026 Coln contributors +-- +-- SPDX-License-Identifier: Apache-2.0 OR MIT + +module Coln.MIR.Top where + +import Data.Traversable (mapAccumL) + +import Coln.Common +import Coln.Core.Globals qualified as Core +import Coln.Core.Memoed qualified as Core +import Coln.Core.Params +import Coln.Core.Readback +import Coln.MIR.Interpret +import Coln.MIR.Layout +import Coln.MIR.Memoed qualified as M +import Coln.MIR.Params (SMLevel (..)) +import Coln.MIR.Realm as MIR +import Coln.MIR.Value qualified as V + +coreToMIR :: V.Globals -> RealmId -> Core.Realm -> MIR.Realm +coreToMIR g rId r = do + let rTy = interpAt STheory g BwdNil r.rootType.stx + let (gens, root) = layoutTop rId rTy + let go :: (Int, V.Locals) -> Core.Definition Local -> ((Int, V.Locals), RealmDefinition) + go (n, ls) def = do + let ty = interpAt STheory g ls $ readb n def.ty + let body = interpAt STheory g ls def.body.stx + let l' = Pair STheory body + let def' = + RealmDefinition + { body = M.fromV n body + , ty = ty + } + ((n + 1, ls :> l'), def') + let (_, defs) = mapAccumL go (1, BwdNil :> Pair STheory root.val) r.realmDefinitions + MIR.Realm + { root = root.val + , rootType = r.rootType.val + , generators = gens + , realmDefinitions = defs + } diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs index cb6b6bd6..3489255d 100644 --- a/packages/coln-compiler/src/Coln/SIR/Cache.hs +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -2,12 +2,15 @@ module Coln.SIR.Cache where import Coln.Common import Coln.Core.Params +import Coln.MIR.Memoed qualified as M import Coln.MIR.Params +import Coln.MIR.Realm qualified as V import Coln.MIR.Value qualified as V import Coln.SIR.Realm import Coln.SIR.Separate import Coln.SIR.Syntax qualified as S +import Control.Arrow (second) import Data.Set qualified as Set data Scope = Scope @@ -19,6 +22,17 @@ data Scope = Scope , realm :: RealmId } +emptyScope :: RealmId -> Scope +emptyScope rId = + Scope + { len = 0 + , ctx = BwdNil + , names = BwdNil + , bound = BwdNil + , used = Set.empty + , realm = rId + } + bind :: Scope -> Maybe Name -> V.Ty Set -> (Name, V.El Set, Scope) bind sc mx a = do let q = separate sc.len a @@ -43,17 +57,19 @@ cloArgName :: V.Clo a b -> Maybe Name cloArgName (V.Clo x _) = Just x cloArgName (V.CloConst _) = Nothing -cache :: Path -> Scope -> V.El Theory -> (Trie Entity, Trie Definition, S.El Theory) -cache p sc v = do +cache :: Name -> Path -> Scope -> V.El Theory -> (Trie Entity, Trie Definition, S.El Theory) +cache x p sc v = do let code u a = do let sa = separate sc.len a - let cols = toList (sc.ctx :> sa) + let x' = case Set.member x sc.used of + True -> freshNameFor sc.used + False -> x + let cols = zip (toList $ sc.names :> x') (toList $ sc.ctx :> sa) let bound = toList (sc.bound :> V.local (FId sc.len)) let boundStx = separate (sc.len + 1) <$> bound - let xs = toList sc.names - let ent = Entity View (zip xs ((.shape) <$> cols)) (Just [0 .. sc.len]) + let ent = Entity View (second (.shape) <$> cols) (Just [0 .. sc.len]) let tn = TableName sc.realm p - let def = Definition (zip xs cols) tn boundStx + let def = Definition cols tn boundStx let prop = S.Atom tn S.Erased boundStx let elt = S.Multi u $ S.Query sa.shape (S.Abs Nothing prop) (Leaf ent, Node (fromList [("definition", Leaf def)]), elt) @@ -62,13 +78,16 @@ cache p sc v = do V.Code SSetU a -> code SSetU a V.Code SPropU a -> code SPropU a V.Lam SSetTheory dom clo -> do - let (x, arg, sc') = bind sc (cloArgName clo) dom - let (ents, defs, body) = cache p sc' (V.appClo clo arg) - (ents, defs, S.Lam (separate sc.len dom) (S.Abs (Just x) body)) + let (x', arg, sc') = bind sc (cloArgName clo) dom + let (ents, defs, body) = cache x p sc' (V.appClo clo arg) + (ents, defs, S.Lam (separate sc.len dom) (S.Abs (Just x') body)) V.Cons fields -> do let (ents, defs, fields') = - unzip3 [cache (p :> x) sc field | (x, field) <- toList fields] + unzip3 [cache x' (p :> x') sc field | (x', field) <- toList fields] ( Node (Dict fields.head (fromList ents)) , Node (Dict fields.head (fromList defs)) , S.Cons (Dict fields.head (fromList fields')) ) + +cacheTop :: RealmId -> Name -> V.RealmDefinition -> (Trie Entity, Trie Definition, S.El Theory) +cacheTop rId x def = cache x (BwdNil :> x) (emptyScope rId) def.body.val diff --git a/packages/coln-compiler/src/Coln/SIR/Realm.hs b/packages/coln-compiler/src/Coln/SIR/Realm.hs index 21a23cf7..e173b7af 100644 --- a/packages/coln-compiler/src/Coln/SIR/Realm.hs +++ b/packages/coln-compiler/src/Coln/SIR/Realm.hs @@ -2,8 +2,11 @@ module Coln.SIR.Realm where import Coln.Common import Coln.Core.Params -import Coln.SIR.Syntax import Coln.Core.Value qualified as CoreV +import Coln.SIR.Syntax + +import Data.Aeson qualified as AE +import GHC.Generics data EntityVariant = Table @@ -22,6 +25,7 @@ data Definition = Definition } data RuleVariant = Enforced | Monitored + deriving (Show, Eq, Generic) data RuleContextSide = Antecedent | Consequent @@ -40,3 +44,9 @@ data Realm = Realm , root :: El Theory , rootType :: CoreV.Ty N } + +-- JSON +-------------------------------------------------------------------------------- + +instance AE.ToJSON RuleVariant where + toEncoding = AE.genericToEncoding aeOptions diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs index f05a3691..cf5bfa19 100644 --- a/packages/coln-compiler/src/Coln/SIR/Separate.hs +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -75,7 +75,7 @@ instance Separate (V.Ty Set) S.Query where separate n a = S.Query (shapeOf a) (S.Abs Nothing (propAt (n + 1) a (V.local (FId n)))) -separateGenerator :: TableName -> V.Generator -> Realm +separateGenerator :: TableName -> V.Generator -> (Maybe (Trie Entity), Maybe (Trie Definition), Maybe (Trie Rule)) separateGenerator tn = \case V.Rel u xs tys -> do let names = toList xs @@ -87,16 +87,16 @@ separateGenerator tn = \case let table = Entity Table (zip names ((.shape) <$> septys)) primaryKey let atom = S.Atom tn S.Erased [S.Var (BId (argNum - i - 1)) | i <- [0 .. argNum - 1]] let foreignKey = Rule Enforced Consequent (zip names septys) atom S.trueProp - Realm{entities = Leaf table, definitions = Node $ fromList [], rules = Node $ fromList [("foreignKey", Leaf foreignKey)]} + (Just $ Leaf table, Nothing, Just $ Node $ fromList [("foreignKey", Leaf foreignKey)]) V.Fun xs tys cod -> case hlevelOf cod of - HUnit -> Realm{entities = Node $ fromList [], definitions = Node $ fromList [], rules = Node $ fromList []} + HUnit -> (Nothing, Nothing, Nothing) HProp -> do let names = toList xs let argNum = length names let septys = uncurry separate <$> zip [0 ..] (toList tys) let codProp = propAt argNum cod V.Erased let rule = Rule Monitored Antecedent (zip names septys) S.trueProp codProp - Realm{entities = Node $ fromList [], definitions = Node $ fromList [], rules = Leaf rule} + (Nothing, Nothing, Just $ Leaf rule) HSet -> do let argNames = toList xs let argNum = length argNames @@ -116,7 +116,7 @@ separateGenerator tn = \case let totalCons = S.Atom tn S.Erased [S.Var (BId (argNum - i - 1)) | i <- [0 .. argNum - 1]] let total = Rule Monitored Antecedent (zip names (take argNum septys)) S.trueProp totalCons - Realm{entities = Leaf table, definitions = Node $ fromList [], rules = Node $ fromList [("foreignKey", Leaf foreignKey), ("total", Leaf total)]} + (Just $ Leaf table, Nothing, Just $ Node $ fromList [("foreignKey", Leaf foreignKey), ("total", Leaf total)]) _ -> panic "bad h-level of cod" -- separateRealm :: V.Realm -> Realm diff --git a/packages/coln-compiler/src/Coln/SIR/Syntax.hs b/packages/coln-compiler/src/Coln/SIR/Syntax.hs index 22cbe5b9..88f7f3db 100644 --- a/packages/coln-compiler/src/Coln/SIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/SIR/Syntax.hs @@ -4,6 +4,9 @@ import Coln.Common import Coln.Core.Params import Coln.MIR.Params +import Data.Aeson qualified as AE +import Data.Aeson.Encoding qualified as AE +import Data.Char (toLower) import GHC.Generics data El :: MLevel -> Type where @@ -49,3 +52,35 @@ data Query = Query { shape :: Shape , pred :: Abs Prop } + +-- JSON +-------------------------------------------------------------------------------- + +aeOptions :: AE.Options +aeOptions = + AE.defaultOptions + { AE.allNullaryToStringTag = True + , AE.constructorTagModifier = \x -> fmap toLower (take 1 x) ++ (drop 1 x) + } + +class PathLike a where + namesOf :: a -> [Name] + +encName :: Name -> AE.Encoding +encName n = AE.list AE.toEncoding $ n.init ++ [n.last] + +encPath :: (PathLike a) => a -> AE.Encoding +encPath = AE.list encName . namesOf + +instance PathLike Path where namesOf = toList + +instance PathLike TableName where namesOf tn = tn.realm : namesOf tn.path + +taggedEncoding :: Text -> AE.Series -> AE.Encoding +taggedEncoding t v = AE.pairs $ AE.pair "tag" (AE.toEncoding t) <> v + +instance AE.ToJSON ScalarType where + toJSON = panic "aesons behaving badly" + toEncoding = \case + RowId e -> taggedEncoding "rowId" $ AE.pair "path" $ encPath e + BuiltinTy bt -> taggedEncoding "builtin" $ AE.pair "type" $ AE.genericToEncoding aeOptions bt diff --git a/packages/coln-compiler/src/Coln/SIR/Top.hs b/packages/coln-compiler/src/Coln/SIR/Top.hs new file mode 100644 index 00000000..75eeb29e --- /dev/null +++ b/packages/coln-compiler/src/Coln/SIR/Top.hs @@ -0,0 +1,57 @@ +-- SPDX-FileCopyrightText: 2026 Coln contributors +-- +-- SPDX-License-Identifier: Apache-2.0 OR MIT + +module Coln.SIR.Top where + +import Control.Arrow ((&&&)) +import Data.Map.Ordered qualified as OMap +import Data.Maybe (fromMaybe) + +import Coln.Common +import Coln.Core.Params +import Coln.MIR.Realm qualified as MIR +import Coln.SIR.Cache +import Coln.SIR.Realm qualified as SIR +import Coln.SIR.Separate + +split3 :: Dict (Maybe x, Maybe y, Maybe z) -> (Maybe (Dict x), Maybe (Dict y), Maybe (Dict z)) +split3 d = do + let d1 = case [(x, y) | (x, (Just y, _, _)) <- toList d] of + [] -> Nothing + pairs -> Just $ fromList pairs + let d2 = case [(x, y) | (x, (_, Just y, _)) <- toList d] of + [] -> Nothing + pairs -> Just $ fromList pairs + let d3 = case [(x, y) | (x, (_, _, Just y)) <- toList d] of + [] -> Nothing + pairs -> Just $ fromList pairs + (d1, d2, d3) + +aggregate3 :: + (TableName -> a -> (Maybe (Trie x), Maybe (Trie y), Maybe (Trie z))) -> + (TableName -> Trie a -> (Maybe (Trie x), Maybe (Trie y), Maybe (Trie z))) +aggregate3 f t (Leaf a) = f t a +aggregate3 f t (Node d) = do + let (d1, d2, d3) = split3 $ aggregate3 f t <$> d + (Node <$> d1, Node <$> d2, Node <$> d3) + +cleanTrie :: Trie a -> Maybe (Trie a) +cleanTrie y@Leaf{} = Just y +cleanTrie (Node d) = case [(x, y) | (x, Just y) <- toList $ fmap cleanTrie d] of + [] -> Nothing + pairs -> Just $ Node $ fromList pairs + +mirToSIR :: RealmId -> MIR.Realm -> SIR.Realm +mirToSIR rId r = do + let root = separate 0 r.root + let (rootE, rootD, rootR) = aggregate3 separateGenerator (TableName rId $ BwdNil :> "root") r.generators + let (names, cached) = unzip $ map (fst &&& uncurry (cacheTop rId)) $ OMap.assocs r.realmDefinitions + let (cachedE, cachedD, _) = unzip3 cached + SIR.Realm + { entities = Node $ fromList [(x, y) | (x, Just y) <- ("root", rootE) : zip names (map cleanTrie cachedE)] + , definitions = Node $ fromList [(x, y) | (x, Just y) <- ("root", rootD) : zip names (map cleanTrie cachedD)] + , rules = Node $ fromList [("root", fromMaybe emptyNode rootR)] + , root = root + , rootType = r.rootType + } diff --git a/packages/coln-compiler/src/Coln/Top.hs b/packages/coln-compiler/src/Coln/Top.hs new file mode 100644 index 00000000..1dd16f25 --- /dev/null +++ b/packages/coln-compiler/src/Coln/Top.hs @@ -0,0 +1,64 @@ +module Coln.Top where + +import Coln.Common +import Coln.Core.Globals +import Coln.Diagnostics (ColnCode) +import Coln.FLIR.Top +import Coln.Frontend.Parser +import Coln.MIR.Interpret qualified as MIR +import Coln.MIR.Top +import Coln.SIR.Realm qualified as SIR +import Coln.SIR.Top + +import Control.Exception +import Data.Aeson qualified as AE +import Data.Foldable (for_) +import Data.Map.Ordered qualified as OMap +import Data.Text qualified as T +import Data.Text.IO qualified as TIO +import System.FilePath (()) +import System.IO (hPutStrLn, stderr) + +data ExitException = Exit + deriving (Show, Eq, Ord) + +instance Exception ExitException + +catchExit :: IO () -> IO () +catchExit action = + try action >>= \case + Right _ -> pure () + Left (_ :: ExitException) -> pure () + +loadFile :: FilePath -> IO (Reporter ColnCode, Globals) +loadFile fp = + try (TIO.readFile fp) >>= \case + Left (err :: IOError) -> do + hPutStrLn stderr $ "could not read file " ++ fp ++ " error: " ++ show err + throw Exit + Right contents -> do + let (rep, g) = compile fp contents + g' <- g + pure (rep, g') + +loadRealms :: FilePath -> IO (Reporter ColnCode, OMap Name SIR.Realm) +loadRealms fp = do + (rep, g) <- loadFile fp + let realmsCore = OMap.assocs g.realms + let globalsMIR = MIR.interpGlobals g + let realmsMIR = [(rId, coreToMIR globalsMIR rId r) | (rId, r) <- realmsCore] + let realmsSIR = [(rId, mirToSIR rId r) | (rId, r) <- realmsMIR] + pure (rep, OMap.fromList realmsSIR) + +compile :: FilePath -> T.Text -> (Reporter ColnCode, IO Globals) +compile fp contents = do + let reporter = fileReporter stderr + let f = newFile fp contents + let top = topFromText reporter f + (reporter, top) + +writeFLIR :: FilePath -> Reporter ColnCode -> OMap Name SIR.Realm -> IO () +writeFLIR fp _ realms = for_ (OMap.assocs realms) $ \(rId, r) -> do + let flir = sirToFLIR rId r + let fn = fp mangleToString rId <> ".json" + AE.encodeFile fn flir diff --git a/packages/coln-compiler/test/Main.hs b/packages/coln-compiler/test/Main.hs index 083eb8e0..637e5369 100644 --- a/packages/coln-compiler/test/Main.hs +++ b/packages/coln-compiler/test/Main.hs @@ -4,13 +4,13 @@ module Main (main) where -import Coln.Backend.Lower import Coln.Backend.TypeScript.Generate qualified as TypeScript import Coln.Common import Coln.Core import Coln.Diagnostics import Coln.Frontend.Notation import Coln.Frontend.Parser +import Coln.Top import Control.Exception (evaluate, finally, onException) import Data.ByteString.Lazy qualified as LBS import Data.Functor.Contravariant (contramap) From 8c20a9b5a9eb8db817c524cb85f9a6e315d1d1ba Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Fri, 28 Aug 2026 19:34:41 +0100 Subject: [PATCH 20/42] sketch of algorithm for layout of initial models --- .../coln-compiler/src/Coln/MIR/Evaluation.hs | 19 ++-- .../coln-compiler/src/Coln/MIR/Interpret.hs | 33 ++++--- packages/coln-compiler/src/Coln/MIR/Layout.hs | 56 ++++++++--- packages/coln-compiler/src/Coln/MIR/Memoed.hs | 30 +++--- .../coln-compiler/src/Coln/MIR/Readback.hs | 24 ++--- packages/coln-compiler/src/Coln/MIR/Realm.hs | 25 +++-- packages/coln-compiler/src/Coln/MIR/Syntax.hs | 43 ++++----- packages/coln-compiler/src/Coln/MIR/Value.hs | 92 ++++++++++++------- 8 files changed, 201 insertions(+), 121 deletions(-) diff --git a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs index 1cd93feb..fc8ad6bc 100644 --- a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs +++ b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs @@ -7,29 +7,30 @@ import Coln.MIR.Params import Coln.MIR.Syntax qualified as S import Coln.MIR.Value qualified as V -class Eval a b where - eval :: V.Locals -> a -> b +class Eval (a :: Case -> MLevel -> Type) (b :: Case -> MLevel -> Type) where + eval :: (V.HasEvaluation c) => V.Locals -> a c l -> V.Evaluation b c l -evalAbs :: (Eval a b) => V.Locals -> S.Abs a -> V.Clo (V.El Set) b +evalAbs :: (V.HasEvaluation c, Eval a b) => V.Locals -> S.Abs (a c l) -> V.Clo (V.El N Set) (V.Evaluation b c l) evalAbs vs (S.Abs x body) = V.Clo x (\v -> eval (vs :> Pair SSet v) body) evalAbs vs (S.AbsConst body) = V.CloConst (eval vs body) -instance Eval (S.El l) (V.El l) where +instance Eval S.El V.El where eval vs = \case - S.LiftEl t -> V.LiftEl LSetTheory (eval vs t) + S.LiftEl t -> V.emap (V.LiftEl LSetTheory) (eval vs t) S.Var i -> levelCoerceFromMatch SSet (elemAt vs i) S.Lookup tn args a -> V.Neu $ V.Neutral (V.Lookup tn (eval vs <$> args) (eval vs a)) BwdNil S.Code u a -> V.Code u (eval vs a) - S.Lam dom abs -> V.Lam SSetTheory (eval vs dom) (evalAbs vs abs) - S.Cons fields -> V.Cons (eval vs <$> fields) + S.Lam dom abs -> V.epure $ V.Lam SSetTheory (eval vs dom) (evalAbs vs abs) + S.Cons fields -> V.epure $ V.Cons (eval vs <$> fields) S.Proj t x -> V.proj (eval vs t) x S.Lit l -> V.Lit l S.Erased -> V.Erased + S.Is t -> V.Become (eval vs t) -instance Eval (S.Ty l) (V.Ty l) where +instance Eval S.Ty V.Ty where eval vs = \case - S.LiftTy t -> V.LiftTy LSetTheory (eval vs t) + S.LiftTy t -> V.emap (V.LiftTy LSetTheory) (eval vs t) S.U u -> V.U u S.EltOf u tn args -> V.EltOf u tn (eval vs <$> args) S.Function ft -> diff --git a/packages/coln-compiler/src/Coln/MIR/Interpret.hs b/packages/coln-compiler/src/Coln/MIR/Interpret.hs index 52348657..3a264ca5 100644 --- a/packages/coln-compiler/src/Coln/MIR/Interpret.hs +++ b/packages/coln-compiler/src/Coln/MIR/Interpret.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE QuantifiedConstraints #-} +{-# LANGUAGE TypeAbstractions #-} module Coln.MIR.Interpret where -- Interpret Core syntax into MIR values @@ -8,42 +10,48 @@ import Coln.Core.Syntax qualified as S import Coln.MIR.Params import Coln.MIR.Value qualified as V -class Interp a (f :: MLevel -> Type) | a -> f where - interp :: V.Globals -> V.Locals -> a -> Match SMLevel f +class Interp (a :: Case -> Type) (f :: Case -> MLevel -> Type) | a -> f where + interp :: (V.HasEvaluation c) => V.Globals -> V.Locals -> a c -> Match SMLevel (V.Evaluation f c) -interpAt :: (Interp a f, LevelCoerce f) => SMLevel l -> V.Globals -> V.Locals -> a -> f l +interpAt :: (Interp a b, forall c'. LevelCoerce (b c'), V.HasEvaluation c) => SMLevel l -> V.Globals -> V.Locals -> a c -> V.Evaluation b c l interpAt l0 g e t = case interp g e t of - Pair l1 v -> levelCoerce l1 l0 v + Pair l1 v -> V.emap (levelCoerce l1 l0) v + -- case V.scase @c of + -- SNominative -> levelCoerce l1 l0 v + -- SDescriptive -> case v of + -- V.Describe v' -> V.Describe $ levelCoerce l1 l0 v' + -- V.Become v' -> V.Become $ levelCoerce l1 l0 v' -- Should this also be "compile"? -instance Interp (S.El c) V.El where +instance Interp S.El V.El where interp g e = \case S.LocalVar i -> elemAt e i S.GlobalVar x _ -> elemAt g x S.Code u a -> withUniverse u $ \su -> do let (l0, l1) = (sDecodesInto su, sCodesInto su) - Pair l1 (V.Code su (interpAt l0 g e a)) + Pair l1 (V.emap (V.Code su) (interpAt l0 g e a)) S.Lam fv dom abs -> withFunctionVariant fv.mlevel $ \sfv -> do let (d, c) = (sDom sfv, sCod sfv) let clo = case abs of S.Abs x body -> V.Clo x (\v -> interpAt c g (e :> Pair d v) body) S.AbsConst body -> V.CloConst (interpAt c g e body) - Pair c (V.Lam sfv (interpAt d g e dom) clo) + Pair c (V.epure $ V.Lam sfv (interpAt d g e dom) clo) S.App fv t0 t1 -> withFunctionVariant fv.mlevel $ \sfv -> do let (d, c) = (sDom sfv, sCod sfv) Pair c (V.app sfv (interpAt c g e t0) (interpAt d g e t1)) S.Cons l fields -> withLevel l.mlevel $ \sl -> do let fields' = interpAt sl g e <$> fields - Pair sl (V.Cons fields') + Pair sl (V.epure $ V.Cons fields') S.Proj l t0 x -> withLevel l.mlevel $ \sl -> do let v = interpAt sl g e t0 Pair sl (V.proj v x) S.Init _ -> panic "cannot interpret init yet" S.Lit l -> Pair SSet (V.Lit l) - S.Is t -> interp g e t + S.Is t -> case interp g e t of + Pair l v -> Pair l (V.Become v) -instance Interp (S.Ty c) V.Ty where +instance Interp S.Ty V.Ty where interp g e = \case S.U u -> withUniverse u $ \su -> Pair (sCodesInto su) (V.U su) S.Decode u t -> withUniverse u $ \su -> @@ -57,11 +65,12 @@ instance Interp (S.Ty c) V.Ty where Pair c (V.Function (V.FunctionType (SFunctionVariant sfv ft.variant.hlevel) dom cod)) S.Record rt -> withLevel rt.level.mlevel $ \sl -> do let rt' = V.RecordType rt.level.hlevel e (flip (interpAt sl g) <$> rt.fieldTypes) - Pair sl (V.Record rt') + Pair sl (V.Become $ V.Record rt') S.Eq et -> do let at = interpAt SSet g e et.at let (lhs, rhs) = (interpAt SSet g e et.lhs, interpAt SSet g e et.rhs) Pair SSet $ V.Eq at lhs rhs S.BuiltinTy t -> do Pair SSet $ V.BuiltinTy t - S.IsTy t -> interp g e t + S.IsTy t -> case interp g e t of + Pair l v -> Pair l (V.Become v) diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs index 22dcb701..0f76b1f3 100644 --- a/packages/coln-compiler/src/Coln/MIR/Layout.hs +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -28,8 +28,8 @@ argName used (V.CloConst _) = freshNameFor used data Scope = Scope { len :: CtxLen , names :: Bwd Name - , ctx :: Bwd (V.Ty Set) - , bound :: Bwd (V.El Set) + , ctx :: Bwd (V.Ty N Set) + , bound :: Bwd (V.El N Set) , locals :: V.Locals , usedNames :: Set.Set Name , realm :: RealmId @@ -38,47 +38,75 @@ data Scope = Scope emptyScope :: RealmId -> Scope emptyScope = Scope 0 BwdNil BwdNil BwdNil BwdNil Set.empty -bind :: Scope -> Name -> V.Ty Set -> (V.El Set, Scope) +bind :: Scope -> Name -> V.Ty N Set -> (V.El N Set, Scope) bind sc x a = do let v = V.local (FId sc.len) sc' = - Scope + sc { len = sc.len + 1 , names = sc.names :> x , ctx = sc.ctx :> a , bound = sc.bound :> v , locals = sc.locals :> Pair SSet v , usedNames = Set.insert x sc.usedNames - , realm = sc.realm } (v, sc') -args :: Scope -> [M.El Set] +args :: Scope -> [M.El N Set] args sc = [M.M (readb sc.len v) v | v <- toList sc.bound] -layout :: Path -> Scope -> V.Ty Theory -> (Trie Generator, M.El Theory) -layout p sc = \case +layout :: Path -> Providence -> Scope -> V.Ty N Theory -> (Trie Generator, M.El N Theory) +layout p pr sc = \case V.LiftTy LSetTheory a -> do - let gt = Leaf (Fun sc.names sc.ctx a) + let gt = Leaf (Generator pr sc.names sc.ctx (GenLift a)) (gt, M.liftEl $ M.lookup (TableName sc.realm p) (args sc) (M.fromV sc.len a)) V.U (inferSetCodes -> u) -> do - let gt = Leaf (Rel u sc.names sc.ctx) + let gt = Leaf (Generator pr sc.names sc.ctx (GenU u)) (gt, M.code u $ M.eltOf u (TableName sc.realm p) (args sc)) V.Function ft -> case ft.variant.mlevel of SSetTheory -> do let x = argName sc.usedNames ft.cod let (v, sc') = bind sc x ft.dom - let (gt, m) = layout p sc' (V.appClo ft.cod v) + let (gt, m) = layout p pr sc' (V.appClo ft.cod v) (gt, M.lam sc.locals (M.fromV sc.len ft.dom) (S.Abs x m.stx)) V.Record rt -> do let go _ [] = ([], []) go l ((x, a) : rest) = do - let (gt, m) = layout (p :> x) sc (a l) + let (gt, m) = layout (p :> x) pr sc (a l) let (gts, ms) = go (l :> Pair STheory m.val) rest (gt : gts, m : ms) let (gts, ms) = go rt.capture (toList rt.fieldTypes) let gt = Node $ Dict rt.fieldTypes.head (Vector.fromList gts) (gt, M.cons (Dict rt.fieldTypes.head (Vector.fromList ms))) -layoutTop :: RealmId -> V.Ty Theory -> (Trie Generator, M.El Theory) -layoutTop x = layout BwdNil (emptyScope x) +layoutTop :: RealmId -> V.Ty N Theory -> (Trie Generator, M.El N Theory) +layoutTop x = layout BwdNil Profane (emptyScope x) + +asNominative :: V.El D Set -> V.El N Set +asNominative = \case + V.Cons fields -> V.Cons $ flip fmap fields $ \case + V.Become v -> v + V.Describe v -> asNominative v + +emptyNode :: Trie Generator +emptyNode = Node $ fromList [] + +declareEvaluation :: Path -> Scope -> V.Evaluation V.El D Theory -> (Trie Generator, M.El N Theory) +declareEvaluation p sc = \case + V.Become v -> (emptyNode, M.fromV sc.len v) + V.Describe v -> declare p sc v + +declare :: Path -> Scope -> V.El D Theory -> (Trie Generator, M.El N Theory) +declare p sc = \case + V.LiftEl LSetTheory v -> (emptyNode, M.liftEl $ M.fromV sc.len $ asNominative v) + V.Lam SSetTheory dom clo -> do + let x = argName sc.usedNames clo + let (v, sc') = bind sc x dom + let (gt, m) = declareEvaluation p sc' (V.appClo clo v) + (gt, M.lam sc.locals (M.fromV sc.len dom) (S.Abs x m.stx)) + V.Cons fields -> do + let (gts, ms) = unzip $ for (toList fields) $ \(x, v) -> + declareEvaluation (p :> x) sc v + (Node $ withHead fields gts, M.cons $ withHead fields ms) + V.Init a -> layout p Holy sc a + diff --git a/packages/coln-compiler/src/Coln/MIR/Memoed.hs b/packages/coln-compiler/src/Coln/MIR/Memoed.hs index 5c34cab5..1cdf97a0 100644 --- a/packages/coln-compiler/src/Coln/MIR/Memoed.hs +++ b/packages/coln-compiler/src/Coln/MIR/Memoed.hs @@ -8,36 +8,36 @@ import Coln.MIR.Readback import Coln.MIR.Syntax qualified as S import Coln.MIR.Value qualified as V -data Memoed (s :: MLevel -> Type) (v :: MLevel -> Type) (l :: MLevel) = M - { stx :: s l - , val :: ~(v l) +data Memoed (s :: Case -> MLevel -> Type) (v :: Case -> MLevel -> Type) (c :: Case) (l :: MLevel) = M + { stx :: s c l + , val :: ~(V.Evaluation v c l) } type El = Memoed S.El V.El type Ty = Memoed S.Ty V.Ty -var :: V.Locals -> BId -> El Set +var :: V.Locals -> BId -> El N Set var vs i = M (S.Var i) (levelCoerceFromMatch SSet (elemAt vs i)) -fromV :: (Readback (a l) (b l)) => CtxLen -> a l -> Memoed b a l -fromV n v = M (readb n v) v +fromV :: (V.HasEvaluation c, Readback (a c l) (b c l)) => CtxLen -> a c l -> Memoed b a c l +fromV n v = M (readb n v) (V.epure v) -liftEl :: El Set -> El Theory -liftEl (M s v) = M (S.LiftEl s) (V.LiftEl LSetTheory v) +liftEl :: (V.HasEvaluation c) => El c Set -> El c Theory +liftEl (M s v) = M (S.LiftEl s) (V.emap (V.LiftEl LSetTheory) v) -lookup :: TableName -> [El Set] -> Ty Set -> El Set +lookup :: TableName -> [El N Set] -> Ty N Set -> El N Set lookup tn args a = M (S.Lookup tn ((.stx) <$> args) a.stx) (V.lookup tn ((.val) <$> args) a.val) -code :: SUniverse Set Theory -> Ty Set -> El Theory +code :: SUniverse Set Theory -> Ty N Set -> El N Theory code u (M s v) = M (S.Code u s) (V.Code u v) -eltOf :: SUniverse Set Theory -> TableName -> [El Set] -> Ty Set +eltOf :: SUniverse Set Theory -> TableName -> [El N Set] -> Ty N Set eltOf u tn args = M (S.EltOf u tn ((.stx) <$> args)) (V.EltOf u tn ((.val) <$> args)) -lam :: V.Locals -> Ty Set -> S.Abs (S.El Theory) -> El Theory +lam :: (V.HasEvaluation c) => V.Locals -> Ty N Set -> S.Abs (S.El c Theory) -> El c Theory lam vs dom abs = do let clo = evalAbs vs abs - M (S.Lam dom.stx abs) (V.Lam SSetTheory dom.val clo) + M (S.Lam dom.stx abs) (V.epure $ V.Lam SSetTheory dom.val clo) -cons :: Dict (El l) -> El l -cons fields = M (S.Cons ((.stx) <$> fields)) (V.Cons ((.val) <$> fields)) +cons :: (V.HasEvaluation c) => Dict (El c l) -> El c l +cons fields = M (S.Cons ((.stx) <$> fields)) (V.epure $ V.Cons ((.val) <$> fields)) diff --git a/packages/coln-compiler/src/Coln/MIR/Readback.hs b/packages/coln-compiler/src/Coln/MIR/Readback.hs index 88224e7d..a29f6bfa 100644 --- a/packages/coln-compiler/src/Coln/MIR/Readback.hs +++ b/packages/coln-compiler/src/Coln/MIR/Readback.hs @@ -11,12 +11,12 @@ type CtxLen = Int class Readback a b | a -> b where readb :: CtxLen -> a -> b -instance Readback V.Head (S.El Set) where +instance Readback V.Head (S.El N Set) where readb n = \case V.Var (FId i) -> S.Var (BId (n - i - 1)) V.Lookup x args a -> S.Lookup x (readb n <$> args) (readb n a) -instance Readback (V.El Set) (S.El Set) where +instance Readback (V.El N Set) (S.El N Set) where readb n = \case V.Neu ne -> do let go t BwdNil = t @@ -26,10 +26,10 @@ instance Readback (V.El Set) (S.El Set) where V.Lit l -> S.Lit l V.Erased -> S.Erased -fresh :: CtxLen -> V.El Set +fresh :: CtxLen -> V.El N Set fresh n = V.local (FId n) -instance Readback (V.Ty Set) (S.Ty Set) where +instance Readback (V.Ty N Set) (S.Ty N Set) where readb n = \case V.EltOf u tn args -> S.EltOf u tn (readb n <$> args) V.BuiltinTy t -> S.BuiltinTy t @@ -41,18 +41,18 @@ instance Readback (V.Ty Set) (S.Ty Set) where let fieldTypes = fromList $ go n rt.capture (toList rt.fieldTypes) S.Record $ S.RecordType rt.hlevel fieldTypes -instance Readback (V.Ty Theory) (S.Ty Theory) where - readb n = \case - V.LiftTy LSetTheory a -> S.LiftTy (readb n a) - V.U SPropU -> S.U SPropU - V.U SSetU -> S.U SSetU - V.Function ft -> undefined +-- instance Readback (V.Ty N Theory) (S.Ty N Theory) where +-- readb n = \case +-- V.LiftTy LSetTheory a -> S.LiftTy (readb n a) +-- V.U SPropU -> S.U SPropU +-- V.U SSetU -> S.U SSetU +-- V.Function ft -> undefined -readbClo :: (Readback a b) => CtxLen -> V.Clo (V.El Set) a -> S.Abs b +readbClo :: (Readback a b) => CtxLen -> V.Clo (V.El N Set) a -> S.Abs b readbClo n (V.Clo x f) = S.Abs x (readb (n + 1) (f (fresh n))) readbClo n (V.CloConst t) = S.AbsConst (readb n t) -instance Readback (V.El Theory) (S.El Theory) where +instance Readback (V.El N Theory) (S.El N Theory) where readb n = \case V.LiftEl LSetTheory v -> S.LiftEl (readb n v) V.Code SPropU a -> S.Code SPropU (readb n a) diff --git a/packages/coln-compiler/src/Coln/MIR/Realm.hs b/packages/coln-compiler/src/Coln/MIR/Realm.hs index 29c3c1bb..9ad05e01 100644 --- a/packages/coln-compiler/src/Coln/MIR/Realm.hs +++ b/packages/coln-compiler/src/Coln/MIR/Realm.hs @@ -6,18 +6,29 @@ import Coln.MIR.Memoed qualified as M import Coln.MIR.Params import Coln.MIR.Value qualified as V -data Generator - = Rel (SUniverse Set Theory) (Bwd Name) (Bwd (V.Ty Set)) - | Fun (Bwd Name) (Bwd (V.Ty Set)) (V.Ty Set) +data Providence + = Holy -- A god-given relation or function, derived from laying out an initial model + | Profane -- A user-edited relation or function, derived from laying out the root theory + +data GenTy + = GenU (SUniverse Set Theory) + | GenLift (V.Ty N Set) + +data Generator = Generator + { providence :: Providence + , paramNames :: Bwd Name + , paramTypes :: Bwd (V.Ty N Set) + , codom :: GenTy + } data RealmDefinition = RealmDefinition - { body :: M.El Theory - , ty :: V.Ty Theory + { body :: M.El N Theory + , ty :: V.Ty N Theory } data Realm = Realm - { root :: V.El Theory - , rootType :: V.Ty Theory + { root :: V.El N Theory + , rootType :: V.Ty N Theory , generators :: Trie Generator , realmDefinitions :: OMap Name RealmDefinition } diff --git a/packages/coln-compiler/src/Coln/MIR/Syntax.hs b/packages/coln-compiler/src/Coln/MIR/Syntax.hs index febbc5e1..f2a52a0d 100644 --- a/packages/coln-compiler/src/Coln/MIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/MIR/Syntax.hs @@ -6,33 +6,34 @@ import Coln.MIR.Params data Abs a = Abs Name a | AbsConst a -data El :: MLevel -> Type where - LiftEl :: El Set -> El Theory - Var :: BId -> El Set - Lookup :: TableName -> [El Set] -> Ty Set -> El Set - Code :: SUniverse Set Theory -> Ty Set -> El Theory - Lam :: Ty Set -> Abs (El Theory) -> El Theory - Cons :: Dict (El l) -> El l - Proj :: El l -> Name -> El l - Lit :: Literal -> El Set - Erased :: El Set +data El :: Case -> MLevel -> Type where + LiftEl :: El c Set -> El c Theory + Var :: BId -> El N Set + Lookup :: TableName -> [El N Set] -> Ty N Set -> El N Set + Code :: SUniverse Set Theory -> Ty N Set -> El N Theory + Lam :: Ty N Set -> Abs (El c Theory) -> El c Theory + Cons :: Dict (El c l) -> El c l + Proj :: El N l -> Name -> El N l + Lit :: Literal -> El N Set + Is :: El N l -> El D l + Erased :: El N Set data FunctionType = FunctionType { variant :: SFunctionVariant Set Theory - , dom :: Ty Set - , cod :: Abs (Ty Theory) + , dom :: Ty N Set + , cod :: Abs (Ty N Theory) } data RecordType l = RecordType { hlevel :: HLevel - , fieldTypes :: Dict (Ty l) + , fieldTypes :: Dict (Ty N l) } -data Ty :: MLevel -> Type where - LiftTy :: Ty Set -> Ty Theory - U :: SUniverse Set Theory -> Ty Theory - EltOf :: SUniverse Set Theory -> TableName -> [El Set] -> Ty Set - Function :: FunctionType -> Ty Theory - Record :: RecordType l -> Ty l - BuiltinTy :: BuiltinTy -> Ty Set - Eq :: Ty Set -> El Set -> El Set -> Ty Set +data Ty :: Case -> MLevel -> Type where + LiftTy :: Ty c Set -> Ty c Theory + U :: SUniverse Set Theory -> Ty N Theory + EltOf :: SUniverse Set Theory -> TableName -> [El N Set] -> Ty N Set + Function :: FunctionType -> Ty N Theory + Record :: RecordType l -> Ty N l + BuiltinTy :: BuiltinTy -> Ty N Set + Eq :: Ty N Set -> El N Set -> El N Set -> Ty N Set diff --git a/packages/coln-compiler/src/Coln/MIR/Value.hs b/packages/coln-compiler/src/Coln/MIR/Value.hs index d2f7c97b..90f9f82b 100644 --- a/packages/coln-compiler/src/Coln/MIR/Value.hs +++ b/packages/coln-compiler/src/Coln/MIR/Value.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE TypeAbstractions #-} module Coln.MIR.Value where import Coln.Common @@ -8,16 +9,16 @@ import Coln.MIR.Params data Head = Var FId - | Lookup TableName [El Set] (Ty Set) + | Lookup TableName [El N Set] (Ty N Set) data Neutral = Neutral { head :: Head , spine :: Bwd Name } -type Locals = Bwd (Match SMLevel El) +type Locals = Bwd (Match SMLevel (El N)) -type Globals = OMap Name (Match SMLevel El) +type Globals = OMap Name (Match SMLevel (El N)) data Clo a b = Clo Name (a -> b) | CloConst b @@ -25,34 +26,35 @@ appClo :: Clo a b -> a -> b appClo (Clo _ f) v = f v appClo (CloConst v) _ = v -data El :: MLevel -> Type where - LiftEl :: Lift l0 l1 -> El l0 -> El l1 - Neu :: Neutral -> El Set - Code :: SUniverse l0 l1 -> Ty l0 -> El l1 - Lam :: SMFunctionVariant l0 l1 -> Ty l0 -> Clo (El l0) (El l1) -> El l1 - Cons :: Dict (El l) -> El l - Lit :: Literal -> El Set - Erased :: El Set - -local :: FId -> El Set +data El :: Case -> MLevel -> Type where + LiftEl :: Lift l0 l1 -> El c l0 -> El c l1 + Neu :: Neutral -> El N Set + Init :: Ty N Theory -> El D Theory + Code :: SUniverse l0 l1 -> Ty N l0 -> El N l1 + Lam :: SMFunctionVariant l0 l1 -> Ty N l0 -> Clo (El N l0) (Evaluation El c l1) -> El c l1 + Cons :: Dict (Evaluation El c l) -> El c l + Lit :: Literal -> El N Set + Erased :: El N Set + +local :: FId -> El N Set local i = Neu $ Neutral (Var i) BwdNil -lookup :: TableName -> [El Set] -> Ty Set -> El Set +lookup :: TableName -> [El N Set] -> Ty N Set -> El N Set lookup tn args a = Neu $ Neutral (Lookup tn args a) BwdNil -app :: SMFunctionVariant l0 l1 -> El l1 -> El l0 -> El l1 +app :: SMFunctionVariant l0 l1 -> El N l1 -> El N l0 -> El N l1 app fv (Lam fv' _ clo) v = case (fv, fv') of (SSetTheory, SSetTheory) -> appClo clo v (STheoryTop, STheoryTop) -> appClo clo v app _ _ _ = panic "can only apply lambda" -proj :: El l -> Name -> El l +proj :: El N l -> Name -> El N l proj (Neu n) x = Neu $ n{spine = n.spine :> x} proj (Cons fields) x = elemAt fields x proj Erased _ = Erased proj _ _ = panic "can only project from neutral or cons" -decode :: SUniverse l0 l1 -> El l1 -> Ty l0 +decode :: SUniverse l0 l1 -> El N l1 -> Ty N l0 decode su (Code su' a) = case (su, su') of (SPropU, SPropU) -> a (SSetU, SPropU) -> a @@ -61,7 +63,7 @@ decode su (Code su' a) = case (su, su') of (STheoryU, STheoryU) -> a decode _ _ = panic "tried to decode a non-code" -instance LevelCoerce El where +instance LevelCoerce (El c) where levelCoerce SSet SSet v = v levelCoerce STheory STheory v = v levelCoerce STop STop v = v @@ -75,26 +77,26 @@ instance LevelCoerce El where data FunctionType (l0 :: MLevel) (l1 :: MLevel) = FunctionType { variant :: SFunctionVariant l0 l1 - , dom :: Ty l0 - , cod :: Clo (El l0) (Ty l1) + , dom :: Ty N l0 + , cod :: Clo (El N l0) (Ty N l1) } data RecordType (l :: MLevel) = RecordType { hlevel :: HLevel , capture :: Locals - , fieldTypes :: Dict (Locals -> Ty l) + , fieldTypes :: Dict (Locals -> Ty N l) } -data Ty :: MLevel -> Type where - LiftTy :: Lift l0 l1 -> Ty l0 -> Ty l1 - U :: SUniverse l0 l1 -> Ty l1 - EltOf :: SUniverse Set Theory -> TableName -> [El Set] -> Ty Set - Function :: FunctionType l0 l1 -> Ty l1 - Record :: RecordType l -> Ty l - BuiltinTy :: BuiltinTy -> Ty Set - Eq :: Ty Set -> El Set -> El Set -> Ty Set +data Ty :: Case -> MLevel -> Type where + LiftTy :: Lift l0 l1 -> Ty c l0 -> Ty c l1 + U :: SUniverse l0 l1 -> Ty N l1 + EltOf :: SUniverse Set Theory -> TableName -> [El N Set] -> Ty N Set + Function :: FunctionType l0 l1 -> Ty N l1 + Record :: RecordType l -> Ty N l + BuiltinTy :: BuiltinTy -> Ty N Set + Eq :: Ty N Set -> El N Set -> El N Set -> Ty N Set -instance LevelCoerce Ty where +instance LevelCoerce (Ty c) where levelCoerce SSet SSet v = v levelCoerce STheory STheory v = v levelCoerce STop STop v = v @@ -106,10 +108,38 @@ instance LevelCoerce Ty where levelCoerce STop SSet (LiftTy LTheoryTop (LiftTy LSetTheory v)) = v levelCoerce _ _ _ = panic "cannot lift" -instance HLevelOf (Ty Set) where +instance HLevelOf (Ty c Set) where hlevelOf = \case EltOf SPropU _ _ -> HProp EltOf SSetU _ _ -> HSet Record rt -> rt.hlevel Eq eat _ _ -> equalityHLevelOf (hlevelOf eat) BuiltinTy _ -> HSet + +type family Evaluation (f :: Case -> MLevel -> Type) (c :: Case) = (r :: MLevel -> Type) | r -> c f where + Evaluation f N = f N + Evaluation f D = Description f + +data Description :: (Case -> MLevel -> Type) -> MLevel -> Type where + Describe :: f D l -> Description f l + Become :: f N l -> Description f l + +class HasEvaluation (c :: Case) where + epure :: a c l -> Evaluation a c l + emap :: (forall c'. (HasEvaluation c') => a c' l0 -> b c' l1) -> Evaluation a c l0 -> Evaluation b c l1 + ebind :: (forall c'. (HasEvaluation c') => a c' l0 -> Evaluation b c' l1) -> Evaluation a c l0 -> Evaluation b c l1 + scase :: SCase c + +instance HasEvaluation N where + epure = id + emap f = f + ebind f = f + scase = SNominative + +instance HasEvaluation D where + epure = Describe + emap f (Describe x) = Describe (f x) + emap f (Become x) = Become (f x) + ebind f (Describe x) = f x + ebind f (Become x) = Become (f x) + scase = SDescriptive From 323c7a6005d5a55b11910f6ce64b63c4d34d972b Mon Sep 17 00:00:00 2001 From: James Deikun Date: Mon, 31 Aug 2026 08:28:45 -0400 Subject: [PATCH 21/42] FLIR pretty printing --- packages/coln-compiler/src/Coln/FLIR/Value.hs | 145 +++++++++++++++++- packages/coln-compiler/src/Coln/Top.hs | 5 +- 2 files changed, 147 insertions(+), 3 deletions(-) diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs index 122e18bc..0b3cac39 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Value.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -2,6 +2,7 @@ module Coln.FLIR.Value where import Coln.Common import Coln.Core.Params +import Coln.Core.Print import Coln.SIR.Realm qualified as SIR import Coln.SIR.Syntax qualified as SIR @@ -10,8 +11,10 @@ import Data.Aeson qualified as AE import Data.Aeson.Encoding qualified as AE import Data.Char (toLower) import Data.Map.Ordered qualified as OMap -import Data.Maybe (fromMaybe) -import Data.Set qualified as Set +import Data.Maybe (fromJust, fromMaybe, mapMaybe) +import Data.String (fromString) +import FNotation qualified as N +import FNotation.Kinds qualified as K import GHC.Generics type ColName = Path @@ -170,3 +173,141 @@ instance AE.ToJSON Rule where instance AE.ToJSON Realm where toJSON = panic "aesons behaving badly" toEncoding r = AE.pairs $ AE.pair "entities" (pathMapEncoding AE.toEncoding r.entities) <> AE.pair "definitions" (pathMapEncoding AE.toEncoding r.definitions) <> AE.pair "rules" (pathMapEncoding AE.toEncoding r.rules) + +-- Pretty-printer +-------------------------------------------------------------------------------- + +entityVariantDeclKeyword :: EntityVariant -> Name +entityVariantDeclKeyword e = Name [] $ case e of + Table -> "table" + View _ -> "view" -- TODO + Index _ _ -> "index" -- TODO + +ruleVariantDeclKeyword :: SIR.RuleVariant -> Name +ruleVariantDeclKeyword e = Name [] $ case e of + SIR.Enforced -> "enforced" + SIR.Monitored -> "monitored" + +toNotationColName :: ColName -> N.Ntn0 +toNotationColName BwdNil = N.Tuple [] () -- Shouldn't happen +toNotationColName (BwdNil :> x) = N.Field x () +toNotationColName (p :> x) = N.Juxt (toNotationColName p) (N.Field x ()) + +instance ToNotationTop Path where + toNotationTop BwdNil = N.Tuple [] () -- Shouldn't happen + toNotationTop (BwdNil :> x) = N.Ident x () + toNotationTop (p :> x) = N.Juxt (toNotationTop p) (N.Field x ()) + +instance ToNotationTop TableName where + toNotationTop tn = foldl (\n p -> N.Juxt n (N.Field p ())) (N.Ident "ℜ" ()) tn.path + +instance ToNotationTop ColType where + toNotationTop = \case + SIR.RowId e -> toNotationTop e + SIR.BuiltinTy bt -> N.Keyword (fromString $ show bt) () + +instance ToNotationTop (ColName, ColType) where + toNotationTop (n, t) = N.Infix (toNotationColName n) (N.Keyword ":" ()) (toNotationTop t) + +instance ToNotationTop (TableName, Entity) where + toNotationTop (tn, e) = do + let keyword = entityVariantDeclKeyword e.entityVariant + let cols = N.Tuple (map toNotationTop e.columns) () + let colsWKey = case e.primaryKey of + Nothing -> cols + Just primaryKey -> N.Infix cols (N.Keyword "primarykey" ()) (N.Tuple (map toNotationColName $ map (fst . (e.columns !!)) primaryKey) ()) + N.Decl keyword (N.Infix (toNotationTop tn) (N.Keyword ":=" ()) colsWKey) () + +instance ToNotationTop Literal where + toNotationTop = \case + LitInt i -> N.Int i () + LitString t -> N.String t () + +toNotationTerm :: [ColName] -> El -> N.Ntn0 +toNotationTerm _ (Lit l) = toNotationTop l +toNotationTerm cs (LocalVar (FId i)) = toNotationTop (cs !! i) +toNotationTerm _ (Param (FId _)) = panic "param" + +toNotationAtom :: OMap TableName [ColName] -> [ColName] -> Atom -> N.Ntn0 +toNotationAtom columnNames cs a = do + let entity = toNotationTop a.entity + let cols = fromJust (OMap.lookup a.entity columnNames) + let field (i, t) = N.Infix (toNotationColName (cols !! i)) (N.Keyword "↦" ()) (toNotationTerm cs t) + let body = N.Juxt entity $ N.Tuple (map field . mapMaybe sequence $ zip [0 ..] a.values) () + case a.rowId of + Nothing -> body + Just r -> N.Infix (toNotationTerm cs r) (N.Keyword "∈" ()) body + +toNotationProp :: OMap TableName [ColName] -> [ColName] -> Prop -> N.Ntn0 +toNotationProp ts cs = \case + PAtom a -> toNotationAtom ts cs a + PEq a b -> N.Infix (toNotationTerm cs a) (N.Keyword "=" ()) (toNotationTerm cs b) + +toNotationConjunction :: [N.Ntn0] -> N.Ntn0 +toNotationConjunction [] = N.Keyword "⊤" () +toNotationConjunction [p] = p +toNotationConjunction (p : ps) = N.Infix p (N.Keyword "∧" ()) (toNotationConjunction ps) +toNotationDefinition :: OMap TableName [ColName] -> (TableName, Definition) -> N.Ntn0 +toNotationDefinition columnNames (tn, r) = do + let keyword = "chased" + let head = foldl' N.Juxt (toNotationTop tn) (fmap toNotationTop (map fst r.vars)) + let ante = toNotationConjunction $ fmap (toNotationProp columnNames $ map fst r.vars) r.antecedents + let cons = toNotationAtom columnNames (map fst r.vars) $ Atom r.definand Nothing $ map Just r.args + let seq = N.Infix ante (N.Keyword "⊢" ()) cons + N.Decl keyword (N.Infix head (N.Keyword ":=" ()) seq) () + +toNotationRule :: OMap TableName [ColName] -> (TableName, Rule) -> N.Ntn0 +toNotationRule columnNames (tn, r) = do + let keyword = ruleVariantDeclKeyword r.ruleVariant + let head = foldl' N.Juxt (toNotationTop tn) (fmap toNotationTop (map fst r.vars)) + let ante = toNotationConjunction $ fmap (toNotationProp columnNames $ map fst r.vars) r.antecedents + let cons = toNotationConjunction $ fmap (toNotationProp columnNames $ map fst r.vars) r.consequents + let seq = N.Infix ante (N.Keyword "⊢" ()) cons + N.Decl keyword (N.Infix head (N.Keyword ":=" ()) seq) () + +instance ToNotationTop Realm where + toNotationTop (Realm es ds rs) = do + let nes = N.Block "entities" Nothing (fmap toNotationTop (OMap.assocs es)) () + let columnNames = fmap (fmap fst . (.columns)) es + let nds = N.Block "definitions" Nothing (fmap (toNotationDefinition columnNames) (OMap.assocs ds)) () + let nrs = N.Block "rules" Nothing (fmap (toNotationRule columnNames) (OMap.assocs rs)) () + N.Block "flatrealm" Nothing [nes, nds, nrs] () + +irLexConfig :: N.ConfTable K.Kind +irLexConfig = + N.confTableFromList + [ ("flatrealm", K.Block) + , ("entities", K.Block) + , ("definitions", K.Block) + , ("rules", K.Block) + , ("table", K.Decl) + , ("view", K.Decl) + , ("index", K.Decl) + , ("chased", K.Decl) + , ("enforced", K.Decl) + , ("monitored", K.Decl) + , ("end", K.End) + , (":=", K.SKeyword) + , ("=", K.SKeyword) + , (":", K.SKeyword) + , ("∈", K.SKeyword) + , ("∧", K.SKeyword) + , ("⊢", K.SKeyword) + , ("↦", K.SKeyword) + , ("⊤", K.SKeyword) + ] + +irParseConfig :: N.ConfTable N.Prec +irParseConfig = + N.confTableFromList + [ (":=", N.Prec 10 N.AssocNon) + , (":", N.Prec 20 N.AssocNon) + , ("⊢", N.Prec 30 N.AssocNon) + , ("∧", N.Prec 35 N.AssocR) + , ("=", N.Prec 40 N.AssocNon) + , ("∈", N.Prec 45 N.AssocNon) + , ("↦", N.Prec 60 N.AssocNon) + ] + +instance DPretty Realm where + dpretty r = N.dprettyWithConfigs irParseConfig irLexConfig $ toNotationTop r diff --git a/packages/coln-compiler/src/Coln/Top.hs b/packages/coln-compiler/src/Coln/Top.hs index 1dd16f25..6f44f4f3 100644 --- a/packages/coln-compiler/src/Coln/Top.hs +++ b/packages/coln-compiler/src/Coln/Top.hs @@ -16,8 +16,9 @@ import Data.Foldable (for_) import Data.Map.Ordered qualified as OMap import Data.Text qualified as T import Data.Text.IO qualified as TIO +import Prettyprinter.Render.Text (hPutDoc) import System.FilePath (()) -import System.IO (hPutStrLn, stderr) +import System.IO (hPutStrLn, stderr, withFile, pattern WriteMode) data ExitException = Exit deriving (Show, Eq, Ord) @@ -62,3 +63,5 @@ writeFLIR fp _ realms = for_ (OMap.assocs realms) $ \(rId, r) -> do let flir = sirToFLIR rId r let fn = fp mangleToString rId <> ".json" AE.encodeFile fn flir + let pn = fp mangleToString rId <> ".pretty" + withFile pn WriteMode $ \h -> hPutDoc h $ dpretty flir From 3b95664834d340c6affa21a91b00b2b3a29841a1 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Fri, 4 Sep 2026 17:19:55 +0100 Subject: [PATCH 22/42] primitive queries --- .../coln-compiler/src/Coln/FLIR/Flatten.hs | 7 ++++--- .../coln-compiler/src/Coln/MIR/Evaluation.hs | 1 + packages/coln-compiler/src/Coln/MIR/Layout.hs | 2 +- packages/coln-compiler/src/Coln/MIR/Memoed.hs | 4 ++-- .../coln-compiler/src/Coln/MIR/Readback.hs | 5 +++-- packages/coln-compiler/src/Coln/MIR/Syntax.hs | 1 + packages/coln-compiler/src/Coln/MIR/Value.hs | 6 ++++++ packages/coln-compiler/src/Coln/SIR/Cache.hs | 4 ++-- .../coln-compiler/src/Coln/SIR/Separate.hs | 19 ++++++++----------- packages/coln-compiler/src/Coln/SIR/Syntax.hs | 8 ++++++-- 10 files changed, 34 insertions(+), 23 deletions(-) diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index 243ad974..40da4a04 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -107,9 +107,10 @@ app l (S.AbsConst body) _ = flatten l body instance Flatten (S.El Set) Els where flatten l = \case S.Var i -> pure $ elemAt l i - S.Single q -> do - v <- fresh (absName q.pred) q.shape - app l q.pred v >>= assert + S.Lookup tn args shape -> do + v <- fresh Nothing shape + args' <- traverse (flatten l) args + assert $ single $ V.PAtom $ V.Atom tn Nothing (Just <$> concatEls (args' ++ [v])) pure v S.Proj t x -> do v <- flatten l t diff --git a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs index fc8ad6bc..b99aaa66 100644 --- a/packages/coln-compiler/src/Coln/MIR/Evaluation.hs +++ b/packages/coln-compiler/src/Coln/MIR/Evaluation.hs @@ -21,6 +21,7 @@ instance Eval S.El V.El where S.Lookup tn args a -> V.Neu $ V.Neutral (V.Lookup tn (eval vs <$> args) (eval vs a)) BwdNil S.Code u a -> V.Code u (eval vs a) + S.PrimCode u tn args -> V.PrimCode u tn (eval vs <$> args) S.Lam dom abs -> V.epure $ V.Lam SSetTheory (eval vs dom) (evalAbs vs abs) S.Cons fields -> V.epure $ V.Cons (eval vs <$> fields) S.Proj t x -> V.proj (eval vs t) x diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs index 64c082d8..d01c990a 100644 --- a/packages/coln-compiler/src/Coln/MIR/Layout.hs +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -62,7 +62,7 @@ layout p pr sc = \case (gt, M.liftEl $ M.lookup (TableName sc.realm p) (args sc) (M.fromV sc.len a)) V.U (inferSetCodes -> u) -> do let gt = Leaf (Generator pr sc.names sc.ctx (GenU u)) - (gt, M.code u $ M.eltOf u (TableName sc.realm p) (args sc)) + (gt, M.primCode u (TableName sc.realm p) (args sc)) V.Function ft -> case ft.variant.mlevel of SSetTheory -> do let x = argName sc.usedNames ft.cod diff --git a/packages/coln-compiler/src/Coln/MIR/Memoed.hs b/packages/coln-compiler/src/Coln/MIR/Memoed.hs index 1cdf97a0..4faf2fd1 100644 --- a/packages/coln-compiler/src/Coln/MIR/Memoed.hs +++ b/packages/coln-compiler/src/Coln/MIR/Memoed.hs @@ -31,8 +31,8 @@ lookup tn args a = M (S.Lookup tn ((.stx) <$> args) a.stx) (V.lookup tn ((.val) code :: SUniverse Set Theory -> Ty N Set -> El N Theory code u (M s v) = M (S.Code u s) (V.Code u v) -eltOf :: SUniverse Set Theory -> TableName -> [El N Set] -> Ty N Set -eltOf u tn args = M (S.EltOf u tn ((.stx) <$> args)) (V.EltOf u tn ((.val) <$> args)) +primCode :: SUniverse Set Theory -> TableName -> [El N Set] -> El N Theory +primCode u tn args = M (S.PrimCode u tn ((.stx) <$> args)) (V.PrimCode u tn ((.val) <$> args)) lam :: (V.HasEvaluation c) => V.Locals -> Ty N Set -> S.Abs (S.El c Theory) -> El c Theory lam vs dom abs = do diff --git a/packages/coln-compiler/src/Coln/MIR/Readback.hs b/packages/coln-compiler/src/Coln/MIR/Readback.hs index d183bf88..78dcaee2 100644 --- a/packages/coln-compiler/src/Coln/MIR/Readback.hs +++ b/packages/coln-compiler/src/Coln/MIR/Readback.hs @@ -6,7 +6,7 @@ import Coln.MIR.Params import Coln.MIR.Syntax qualified as S import Coln.MIR.Value qualified as V -import Data.Traversable (mapAccumL) +-- import Data.Traversable (mapAccumL) type CtxLen = Int @@ -52,7 +52,7 @@ instance Readback (V.Ty N Set) (S.Ty N Set) where -- V.Function ft -> case ft.variant.mlevel of -- SSetTheory -> S.Function (S.FunctionType ft.variant (readb n ft.dom) (readbClo n ft.cod)) -- V.Record rt -> S.Record (S.RecordType rt.hlevel (readbTele n rt.capture rt.fieldTypes)) --- +-- -- readbTele :: (Traversable f, Readback a b) => CtxLen -> V.Locals -> f (V.Locals -> a) -> f b -- readbTele n l = snd . mapAccumL (\(n', l') k -> ((n' + 1, l' :> Pair SSet (V.local (FId n'))), readb n' $ k l')) (n, l) @@ -65,5 +65,6 @@ instance Readback (V.El N Theory) (S.El N Theory) where V.LiftEl LSetTheory v -> S.LiftEl (readb n v) V.Code SPropU a -> S.Code SPropU (readb n a) V.Code SSetU a -> S.Code SSetU (readb n a) + V.PrimCode u tn args -> S.PrimCode u tn (readb n <$> args) V.Lam SSetTheory dom clo -> S.Lam (readb n dom) (readbClo n clo) V.Cons fields -> S.Cons $ readb n <$> fields diff --git a/packages/coln-compiler/src/Coln/MIR/Syntax.hs b/packages/coln-compiler/src/Coln/MIR/Syntax.hs index f2a52a0d..77f38211 100644 --- a/packages/coln-compiler/src/Coln/MIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/MIR/Syntax.hs @@ -11,6 +11,7 @@ data El :: Case -> MLevel -> Type where Var :: BId -> El N Set Lookup :: TableName -> [El N Set] -> Ty N Set -> El N Set Code :: SUniverse Set Theory -> Ty N Set -> El N Theory + PrimCode :: SUniverse Set Theory -> TableName -> [El N Set] -> El N Theory Lam :: Ty N Set -> Abs (El c Theory) -> El c Theory Cons :: Dict (El c l) -> El c l Proj :: El N l -> Name -> El N l diff --git a/packages/coln-compiler/src/Coln/MIR/Value.hs b/packages/coln-compiler/src/Coln/MIR/Value.hs index 90f9f82b..b2dec620 100644 --- a/packages/coln-compiler/src/Coln/MIR/Value.hs +++ b/packages/coln-compiler/src/Coln/MIR/Value.hs @@ -31,6 +31,7 @@ data El :: Case -> MLevel -> Type where Neu :: Neutral -> El N Set Init :: Ty N Theory -> El D Theory Code :: SUniverse l0 l1 -> Ty N l0 -> El N l1 + PrimCode :: SUniverse Set Theory -> TableName -> [El N Set] -> El N Theory Lam :: SMFunctionVariant l0 l1 -> Ty N l0 -> Clo (El N l0) (Evaluation El c l1) -> El c l1 Cons :: Dict (Evaluation El c l) -> El c l Lit :: Literal -> El N Set @@ -61,6 +62,11 @@ decode su (Code su' a) = case (su, su') of (SSetU, SSetU) -> a (SPropU, SSetU) -> panic "tried to decode a set into a proposition" (STheoryU, STheoryU) -> a +decode su (PrimCode su' tn args) = case (su, su') of + (SPropU, SPropU) -> EltOf su' tn args + (SSetU, SSetU) -> EltOf su' tn args + (SSetU, SPropU) -> EltOf su' tn args + (SPropU, SSetU) -> panic "tried to decode a set into a proposition" decode _ _ = panic "tried to decode a non-code" instance LevelCoerce (El c) where diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs index dcb17fbd..24d07829 100644 --- a/packages/coln-compiler/src/Coln/SIR/Cache.hs +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -70,13 +70,13 @@ cache x p sc v = do let ent = Entity (View Materialized) (second (.shape) <$> cols) (Just [0 .. sc.len]) let tn = TableName sc.realm p let def = Definition cols tn boundStx - let prop = S.Atom tn S.Erased boundStx - let elt = S.Multi u $ S.Query sa.shape (S.Abs Nothing prop) + let elt = S.SelectLast u tn (separate sc.len <$> toList sc.bound) (shapeOf a) (Leaf ent, Node (fromList [("definition", Leaf def)]), elt) case v of V.LiftEl LSetTheory v -> (emptyNode, emptyNode, S.LiftEl (separate sc.len v)) V.Code SSetU a -> code SSetU a V.Code SPropU a -> code SPropU a + V.PrimCode u tn args -> (emptyNode, emptyNode, S.SelectRowId u tn (separate sc.len <$> args)) V.Lam SSetTheory dom clo -> do let (x', arg, sc') = bind sc (cloArgName clo) dom let (ents, defs, body) = cache x p sc' (V.appClo clo arg) diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs index b65f5c78..e93fc917 100644 --- a/packages/coln-compiler/src/Coln/SIR/Separate.hs +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -19,10 +19,7 @@ class Separate a b | a -> b where instance Separate V.Head (S.El Set) where separate n = \case V.Var (FId i) -> S.Var (BId (n - i - 1)) - V.Lookup tn args ret -> do - let args' = separate (n + 1) <$> args - let pred = S.Atom tn S.Erased (args' ++ [S.Var 0]) - S.Single $ S.Query (shapeOf ret) (S.Abs Nothing pred) + V.Lookup tn args ret -> S.Lookup tn (separate n <$> args) (shapeOf ret) instance Separate (V.El N Set) (S.El Set) where separate n = \case @@ -38,13 +35,13 @@ separateClo :: (Separate a b) => CtxLen -> V.Clo (V.El N Set) a -> S.Abs b separateClo n (V.Clo x body) = S.Abs (Just x) (separate (n + 1) (body (V.local (FId n)))) separateClo n (V.CloConst body) = S.AbsConst (separate n body) -instance Separate (V.El N Theory) (S.El Theory) where - separate n = \case - V.LiftEl LSetTheory v -> S.LiftEl (separate n v) - V.Code SSetU a -> S.Multi SSetU (separate n a) - V.Code SPropU a -> S.Multi SPropU (separate n a) - V.Lam SSetTheory dom clo -> S.Lam (separate n dom) (separateClo n clo) - V.Cons fields -> S.Cons $ separate n <$> fields +-- instance Separate (V.El N Theory) (S.El Theory) where +-- separate n = \case +-- V.LiftEl LSetTheory v -> S.LiftEl (separate n v) +-- V.Code SSetU a -> S.Multi SSetU (separate n a) +-- V.Code SPropU a -> S.Multi SPropU (separate n a) +-- V.Lam SSetTheory dom clo -> S.Lam (separate n dom) (separateClo n clo) +-- V.Cons fields -> S.Cons $ separate n <$> fields shapeOf :: V.Ty N Set -> S.Shape shapeOf = \case diff --git a/packages/coln-compiler/src/Coln/SIR/Syntax.hs b/packages/coln-compiler/src/Coln/SIR/Syntax.hs index 88f7f3db..df1cd04d 100644 --- a/packages/coln-compiler/src/Coln/SIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/SIR/Syntax.hs @@ -9,12 +9,16 @@ import Data.Aeson.Encoding qualified as AE import Data.Char (toLower) import GHC.Generics +data PrimQuery + = PrimaryKey TableName [El Set] + data El :: MLevel -> Type where LiftEl :: El Set -> El Theory Var :: BId -> El Set - Single :: Query -> El Set + Lookup :: TableName -> [El Set] -> Shape -> El Set Proj :: El Set -> Name -> El Set - Multi :: SUniverse Set Theory -> Query -> El Theory + SelectRowId :: SUniverse Set Theory -> TableName -> [El Set] -> El Theory + SelectLast :: SUniverse Set Theory -> TableName -> [El Set] -> Shape -> El Theory Lam :: Query -> Abs (El Theory) -> El Theory Cons :: Dict (El l) -> El l Lit :: Literal -> El Set From 994dbb32c16425af369eb2317a2cd82a6e780d3c Mon Sep 17 00:00:00 2001 From: James Deikun Date: Sun, 6 Sep 2026 23:43:03 -0400 Subject: [PATCH 23/42] full pipeline --- packages/coln-compiler/src/Coln/MIR/Top.hs | 26 +++++++++++--------- packages/coln-compiler/src/Coln/SIR/Cache.hs | 2 +- packages/coln-compiler/src/Coln/SIR/Top.hs | 17 +++++++++---- packages/coln-compiler/src/Coln/Top.hs | 3 +-- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/packages/coln-compiler/src/Coln/MIR/Top.hs b/packages/coln-compiler/src/Coln/MIR/Top.hs index 7c36a722..72205c80 100644 --- a/packages/coln-compiler/src/Coln/MIR/Top.hs +++ b/packages/coln-compiler/src/Coln/MIR/Top.hs @@ -4,6 +4,7 @@ module Coln.MIR.Top where +import Control.Arrow ((***)) import Data.Map.Ordered qualified as OMap import Data.Traversable (mapAccumL) @@ -25,8 +26,8 @@ interpGlobals g = foldl go OMap.empty $ OMap.assocs g.definitions interp' :: V.Globals -> Name -> Core.Definition Global -> Match SMLevel (V.El N) interp' acc x def = case interp acc BwdNil def.body.stx of Pair l decl -> do - let declT = levelCoerce l STheory decl - let nomT = snd $ declare (BwdNil :> x) (emptyScope "shouldNeverBeUsed") declT + let declT = V.emap (levelCoerce l STheory) decl + let nomT = snd $ declareEvaluation (BwdNil :> x) (emptyScope "shouldNeverBeUsed") declT let nom = levelCoerce STheory l nomT.val Pair l nom go :: V.Globals -> (Name, Core.Definition Global) -> V.Globals @@ -35,22 +36,23 @@ interpGlobals g = foldl go OMap.empty $ OMap.assocs g.definitions coreToMIR :: V.Globals -> RealmId -> Core.Realm -> MIR.Realm coreToMIR g rId r = do let rTy = interpAt STheory g BwdNil r.rootType.stx - let (gens, root) = layoutTop rId rTy - let go :: (Int, V.Locals) -> Core.Definition Local -> ((Int, V.Locals), RealmDefinition) - go (n, ls) def = do + let (rootgens, rootbody) = layoutTop rId rTy + let go :: (Int, V.Locals) -> (Name, Core.Definition Local) -> ((Int, V.Locals), (Name, (Trie Generator, RealmDefinition))) + go (n, ls) (x, def) = do let ty = interpAt STheory g ls $ readb n def.ty - let body = interpAt STheory g ls def.body.stx - let l' = Pair STheory body + let bodyD = interpAt STheory g ls def.body.stx + let (gens, body) = declareEvaluation (BwdNil :> "init" :> x) (emptyScope rId) bodyD + let l' = Pair STheory body.val let def' = RealmDefinition - { body = M.fromV n body + { body = body , ty = ty } - ((n + 1, ls :> l'), def') - let (_, defs) = mapAccumL go (1, BwdNil :> Pair STheory root.val) r.realmDefinitions + ((n + 1, ls :> l'), (x, (gens, def'))) + let (gens, defs) = fromList *** OMap.fromList $ unzip $ fmap (\(x,(y,z)) -> ((x,y),(x,z))) $ snd $ mapAccumL go (1, BwdNil :> Pair STheory rootbody.val) $ OMap.assocs r.realmDefinitions MIR.Realm - { root = root.val + { root = rootbody.val , rootType = r.rootType.val - , generators = gens + , generators = Node $ fromList $ [("root", rootgens), ("init", Node gens)] , realmDefinitions = defs } diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs index 24d07829..9d929099 100644 --- a/packages/coln-compiler/src/Coln/SIR/Cache.hs +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -90,4 +90,4 @@ cache x p sc v = do ) cacheTop :: RealmId -> Name -> V.RealmDefinition -> (Trie Entity, Trie Definition, S.El Theory) -cacheTop rId x def = cache x (BwdNil :> x) (emptyScope rId) def.body.val +cacheTop rId x def = cache x (BwdNil :> "view" :> x) (emptyScope rId) def.body.val diff --git a/packages/coln-compiler/src/Coln/SIR/Top.hs b/packages/coln-compiler/src/Coln/SIR/Top.hs index 75eeb29e..e6603c43 100644 --- a/packages/coln-compiler/src/Coln/SIR/Top.hs +++ b/packages/coln-compiler/src/Coln/SIR/Top.hs @@ -42,16 +42,23 @@ cleanTrie (Node d) = case [(x, y) | (x, Just y) <- toList $ fmap cleanTrie d] of [] -> Nothing pairs -> Just $ Node $ fromList pairs +fromNode :: Maybe (Trie a) -> [(Name, Trie a)] +fromNode Nothing = [] +fromNode (Just Leaf{}) = panic "leaf at top of generator trie" +fromNode (Just (Node d)) = toList d + mirToSIR :: RealmId -> MIR.Realm -> SIR.Realm mirToSIR rId r = do - let root = separate 0 r.root - let (rootE, rootD, rootR) = aggregate3 separateGenerator (TableName rId $ BwdNil :> "root") r.generators + let (_, _, root) = cache "root" (BwdNil :> "root") (emptyScope rId) r.root + let (rootE, rootD, rootR) = aggregate3 separateGenerator (TableName rId $ BwdNil) r.generators let (names, cached) = unzip $ map (fst &&& uncurry (cacheTop rId)) $ OMap.assocs r.realmDefinitions let (cachedE, cachedD, _) = unzip3 cached + let viewE = Node $ fromList [(x, y) | (x, Just y) <- zip names (map cleanTrie cachedE)] + let viewD = Node $ fromList [(x, y) | (x, Just y) <- zip names (map cleanTrie cachedD)] SIR.Realm - { entities = Node $ fromList [(x, y) | (x, Just y) <- ("root", rootE) : zip names (map cleanTrie cachedE)] - , definitions = Node $ fromList [(x, y) | (x, Just y) <- ("root", rootD) : zip names (map cleanTrie cachedD)] - , rules = Node $ fromList [("root", fromMaybe emptyNode rootR)] + { entities = Node $ fromList $ fromNode rootE ++ [("view", viewE)] + , definitions = Node $ fromList $ fromNode rootD ++ [("view", viewD)] + , rules = fromMaybe emptyNode rootR , root = root , rootType = r.rootType } diff --git a/packages/coln-compiler/src/Coln/Top.hs b/packages/coln-compiler/src/Coln/Top.hs index 6f44f4f3..7657fa8c 100644 --- a/packages/coln-compiler/src/Coln/Top.hs +++ b/packages/coln-compiler/src/Coln/Top.hs @@ -5,7 +5,6 @@ import Coln.Core.Globals import Coln.Diagnostics (ColnCode) import Coln.FLIR.Top import Coln.Frontend.Parser -import Coln.MIR.Interpret qualified as MIR import Coln.MIR.Top import Coln.SIR.Realm qualified as SIR import Coln.SIR.Top @@ -46,7 +45,7 @@ loadRealms :: FilePath -> IO (Reporter ColnCode, OMap Name SIR.Realm) loadRealms fp = do (rep, g) <- loadFile fp let realmsCore = OMap.assocs g.realms - let globalsMIR = MIR.interpGlobals g + let globalsMIR = interpGlobals g let realmsMIR = [(rId, coreToMIR globalsMIR rId r) | (rId, r) <- realmsCore] let realmsSIR = [(rId, mirToSIR rId r) | (rId, r) <- realmsMIR] pure (rep, OMap.fromList realmsSIR) From 5fad573f6be947c6a4fcd02ef56b39927a3c122e Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Thu, 3 Sep 2026 18:20:10 +0100 Subject: [PATCH 24/42] rpc using WireValue --- Cargo.lock | 66 +++++++++++++++++++++++ Cargo.toml | 4 +- packages/coln-flir-rs/Cargo.toml | 5 +- packages/coln-flir-rs/src/ir/mod.rs | 3 +- packages/coln-rpc/Cargo.toml | 21 ++++++++ packages/coln-rpc/scripts/export.rs | 14 +++++ packages/coln-rpc/src/api.rs | 55 +++++++++++++++++++ packages/coln-rpc/src/lib.rs | 1 + packages/coln-rpc/types.ts | 24 +++++++++ packages/coln-store/Cargo.toml | 3 +- packages/coln-store/src/commit/hash.rs | 9 +++- packages/coln-store/src/table/cell.rs | 5 +- packages/coln-store/src/txn/mod.rs | 4 +- packages/coln-store/src/txn/row_handle.rs | 13 +++-- packages/coln-store/src/value.rs | 5 +- 15 files changed, 217 insertions(+), 15 deletions(-) create mode 100644 packages/coln-rpc/Cargo.toml create mode 100644 packages/coln-rpc/scripts/export.rs create mode 100644 packages/coln-rpc/src/api.rs create mode 100644 packages/coln-rpc/src/lib.rs create mode 100644 packages/coln-rpc/types.ts diff --git a/Cargo.lock b/Cargo.lock index 9ae117d9..5270e5c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" + [[package]] name = "actix-codec" version = "0.5.3" @@ -1053,6 +1059,7 @@ dependencies = [ "coln-flir-rs", "serde", "serde_json", + "specta", ] [[package]] @@ -1097,6 +1104,19 @@ dependencies = [ "thiserror 2.0.20", ] +[[package]] +name = "coln-rpc" +version = "0.0.1" +dependencies = [ + "coln-flir-rs", + "coln-store", + "serde", + "serde_json", + "specta", + "specta-serde", + "specta-typescript", +] + [[package]] name = "coln-store" version = "0.1.0" @@ -1120,6 +1140,7 @@ dependencies = [ "serde", "serde_json", "shlex", + "specta", "sqlparser", "subduction_core", "subduction_crypto", @@ -2397,6 +2418,9 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hexane" @@ -4509,6 +4533,48 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "specta" +version = "2.0.0-rc.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f9a30cbcbb7011f1da7d73483983bf838af123883e45f2b36ed76328df9c50" +dependencies = [ + "rustc_version", + "specta-macros", +] + +[[package]] +name = "specta-macros" +version = "2.0.0-rc.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ce14957ecc2897f1f848b8255b6531d13ddf49cbcf506b7c2c9fb1d005593bb" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "specta-serde" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8a72b755ddb8949fd8f17c5db43f0e8a806ea587d9bc602ee3f73240c00029" +dependencies = [ + "specta", + "specta-macros", +] + +[[package]] +name = "specta-typescript" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "639404ee95557f2f8b7e4cb773ffefd45304c7ab8ba21ac83b69051595e083c0" +dependencies = [ + "serde", + "specta", +] + [[package]] name = "spin" version = "0.9.9" diff --git a/Cargo.toml b/Cargo.toml index 72da7b71..9328edda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,9 @@ members = [ "packages/coln-query", "packages/coln-integrator", "packages/coln-batch", + "packages/coln-batch", + "packages/coln-rpc" ] -resolver = "3" [workspace.package] version = "0.0.1" @@ -22,6 +23,7 @@ anyhow = "1.0.102" criterion = "0.8.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.149" +specta = { version = "2.0.0-rc.25", features = ["derive"] } thiserror = "2.0.18" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } diff --git a/packages/coln-flir-rs/Cargo.toml b/packages/coln-flir-rs/Cargo.toml index 9e7b9543..16f344e4 100644 --- a/packages/coln-flir-rs/Cargo.toml +++ b/packages/coln-flir-rs/Cargo.toml @@ -16,8 +16,9 @@ exclude = ["/.gitignore"] test-utils = [] [dependencies] -serde = { workspace = true } -serde_json = { workspace = true } +serde.workspace = true +serde_json.workspace = true +specta.workspace = true [dev-dependencies] # This is a self-referential dev-dependency to have the feature-gated diff --git a/packages/coln-flir-rs/src/ir/mod.rs b/packages/coln-flir-rs/src/ir/mod.rs index e7b8ff16..75d39ebd 100644 --- a/packages/coln-flir-rs/src/ir/mod.rs +++ b/packages/coln-flir-rs/src/ir/mod.rs @@ -6,13 +6,14 @@ pub mod path; use serde::de::Error as DeError; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use specta::Type; // A QName is a vec of string, potentially separated by a forward slash / pub type QName = Vec; // For example a G.V would become [["G"], ["V"]], this is at a higher level than // QName because V would be a query inside a theory G -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Type)] #[serde(transparent)] pub struct Path(pub Vec); diff --git a/packages/coln-rpc/Cargo.toml b/packages/coln-rpc/Cargo.toml new file mode 100644 index 00000000..fa89984a --- /dev/null +++ b/packages/coln-rpc/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "coln-rpc" +edition = "2024" +version.workspace = true +authors.workspace = true +description.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +coln-flir-rs = { version = "0.1.0", path = "../coln-flir-rs" } +coln-store = { version = "0.1.0", path = "../coln-store" } +serde.workspace = true +serde_json.workspace = true +specta.workspace = true +specta-serde = "0.0.12" +specta-typescript = { version = "0.0.12", features = ["serde"] } + +[[bin]] +name = "export" +path = "scripts/export.rs" diff --git a/packages/coln-rpc/scripts/export.rs b/packages/coln-rpc/scripts/export.rs new file mode 100644 index 00000000..4b9ac761 --- /dev/null +++ b/packages/coln-rpc/scripts/export.rs @@ -0,0 +1,14 @@ +use specta::Types; +use specta_typescript::Typescript; +use coln_rpc::api::*; + +fn main() { + let mut types = Types::default(); + + types.register_mut::(); + types.register_mut::(); + + Typescript::default() + .export_to("./types.ts", &types, specta_serde::Format) + .unwrap(); +} diff --git a/packages/coln-rpc/src/api.rs b/packages/coln-rpc/src/api.rs new file mode 100644 index 00000000..86f48261 --- /dev/null +++ b/packages/coln-rpc/src/api.rs @@ -0,0 +1,55 @@ +use coln_flir_rs::ir; +use serde::{Deserialize, Serialize}; +use specta::Type; +// use coln_store::id_packer::IdPacker; +use coln_store::{table::{WireValue}, txn::TxnWireRowId}; + +#[derive(Type, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum WhereClause { + PrimaryKey { values: Vec }, + ExceptRowId { values: Vec }, + Generic { values_at: Vec<(u32, WireValue)> }, +} + +#[derive(Type, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum SelectClause { + All { columns: Vec }, + One { columns: Vec }, + Existence, +} + +#[derive(Type, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum Query { + SelectWhere { + table_name: ir::Path, + select: SelectClause, + r#where: WhereClause, + }, +} + +#[derive(Type, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum QueryResponse { + All { tuples: Vec> }, + One { values: Vec }, + Present, + Absent, +} + +#[derive(Type, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum Mutation { + Insert { + table_name: ir::Path, + columns: Vec, + }, +} + +#[derive(Type, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum MutationResponse { + Id(TxnWireRowId), +} diff --git a/packages/coln-rpc/src/lib.rs b/packages/coln-rpc/src/lib.rs new file mode 100644 index 00000000..e5fdf85e --- /dev/null +++ b/packages/coln-rpc/src/lib.rs @@ -0,0 +1 @@ +pub mod api; diff --git a/packages/coln-rpc/types.ts b/packages/coln-rpc/types.ts new file mode 100644 index 00000000..0b9fef8a --- /dev/null +++ b/packages/coln-rpc/types.ts @@ -0,0 +1,24 @@ +// This file has been generated by Specta. Do not edit this file manually. +export type CommitHash = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number]; + +export type Path = string[][]; + +export type Query = { type: "SelectWhere"; table_name: Path; select: SelectClause; where: WhereClause }; + +export type QueryResponse = { type: "All"; tuples: Value[][] } | { type: "One"; values: Value[] } | { type: "Present" } | { type: "Absent" }; + +export type SelectClause = { type: "All"; columns: number[] } | { type: "One"; columns: number[] } | { type: "Existence" }; + +export type Value = I | number | string; + +export type WhereClause = { type: "PrimaryKey"; values: Value[] } | { type: "ExceptRowId"; values: Value[] } | { type: "Generic"; values_at: ([number, Value])[] }; + +/** + * The unique id that identifies each row in a table. + * + * It is managed by the database and read-only for the user. + */ +export type WireRowId = { + commit: CommitHash, + counter: number, +}; diff --git a/packages/coln-store/Cargo.toml b/packages/coln-store/Cargo.toml index bbf4d804..d415a66b 100644 --- a/packages/coln-store/Cargo.toml +++ b/packages/coln-store/Cargo.toml @@ -25,7 +25,7 @@ coln-flir-rs = { path = "../coln-flir-rs" } csv = "1.4.0" coln-query = { path = "../coln-query", optional = true } ena = "0.14.4" -hex = "0.4.3" +hex = { version = "0.4.3", features = ["serde"] } hexane = "1.0.0-alpha.5" js-sys = { version = "0.3.83", optional = true } leb128 = "0.2.6" @@ -42,6 +42,7 @@ tracing-subscriber = { workspace = true, features = [ "env-filter", "fmt", ], optional = true } +specta.workspace = true [dev-dependencies] diff --git a/packages/coln-store/src/commit/hash.rs b/packages/coln-store/src/commit/hash.rs index 26532c29..ad0e3e67 100644 --- a/packages/coln-store/src/commit/hash.rs +++ b/packages/coln-store/src/commit/hash.rs @@ -3,12 +3,17 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use std::fmt; +use serde::{Serialize, Deserialize}; +use specta::Type; /// The number of bytes in a commit hash. pub(crate) const HASH_SIZE: usize = 32; -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] -pub struct CommitHash(pub [u8; HASH_SIZE]); +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize, Type)] +pub struct CommitHash( + #[serde(with = "hex::serde")] + pub [u8; HASH_SIZE] +); impl CommitHash { pub(crate) fn as_bytes(&self) -> &[u8] { diff --git a/packages/coln-store/src/table/cell.rs b/packages/coln-store/src/table/cell.rs index 069ff1c7..609f9a04 100644 --- a/packages/coln-store/src/table/cell.rs +++ b/packages/coln-store/src/table/cell.rs @@ -3,6 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use std::fmt; +use serde::{Serialize, Deserialize}; +use specta::Type; use crate::column_map::ColIndex; use crate::commit::hash::CommitHash; @@ -11,10 +13,11 @@ use crate::value::Value; use super::ValidationError; + /// The unique id that identifies each row in a table. /// /// It is managed by the database and read-only for the user. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize, Type)] pub struct WireRowId { pub commit: CommitHash, pub counter: u32, diff --git a/packages/coln-store/src/txn/mod.rs b/packages/coln-store/src/txn/mod.rs index 8ce13690..15ce5f80 100644 --- a/packages/coln-store/src/txn/mod.rs +++ b/packages/coln-store/src/txn/mod.rs @@ -14,8 +14,8 @@ use crate::{ }; use inner::TxnInner; -pub(crate) use row_handle::{PendingOp, TempRowId, TxnWireRowId, TxnWireValue}; -pub use row_handle::{TxnId, TxnLiveRowId, TxnLiveValue, empty_row}; +pub(crate) use row_handle::{PendingOp, TempRowId}; +pub use row_handle::{TxnId, TxnLiveRowId, TxnLiveValue, TxnWireRowId, TxnWireValue, empty_row}; pub struct Transaction<'a> { inner: TxnInner, diff --git a/packages/coln-store/src/txn/row_handle.rs b/packages/coln-store/src/txn/row_handle.rs index a8e65744..0f22473a 100644 --- a/packages/coln-store/src/txn/row_handle.rs +++ b/packages/coln-store/src/txn/row_handle.rs @@ -4,6 +4,9 @@ use std::{cell::RefCell, rc::Rc}; +use serde::{Serialize, Deserialize}; +use specta::Type; + use crate::{ commit::hash::CommitHash, op::Op, @@ -161,8 +164,9 @@ pub fn empty_row() -> Vec { } /// A temporary row ID that is valid only within a transaction. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub(crate) struct TempRowId(pub(crate) u32); +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Type)] +#[serde(transparent)] +pub struct TempRowId(pub u32); impl TempRowId { pub(crate) fn resolve(self, commit: CommitHash) -> WireRowId { @@ -184,8 +188,9 @@ impl From for TempRowId { } /// A reference to an existing row or a pending row in the current transaction. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub(crate) enum TxnWireRowId { +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Type)] +#[serde(tag = "type")] +pub enum TxnWireRowId { Existing(WireRowId), Pending(TempRowId), } diff --git a/packages/coln-store/src/value.rs b/packages/coln-store/src/value.rs index bdbf232a..32bcf2a1 100644 --- a/packages/coln-store/src/value.rs +++ b/packages/coln-store/src/value.rs @@ -1,8 +1,11 @@ // SPDX-FileCopyrightText: 2026 Coln contributors // // SPDX-License-Identifier: Apache-2.0 OR MIT +use serde::{Serialize, Deserialize}; +use specta::Type; -#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] +#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize, Type)] +#[serde(untagged)] pub enum Value { Id(I), Int(i32), From 0a5969408e1d51722dff728f7423a88b77c880f0 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Fri, 4 Sep 2026 11:47:05 +0100 Subject: [PATCH 25/42] store hashes as hex strings --- packages/coln-rpc/types.ts | 2 +- packages/coln-store/src/commit/hash.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/coln-rpc/types.ts b/packages/coln-rpc/types.ts index 0b9fef8a..785bc0e2 100644 --- a/packages/coln-rpc/types.ts +++ b/packages/coln-rpc/types.ts @@ -1,5 +1,5 @@ // This file has been generated by Specta. Do not edit this file manually. -export type CommitHash = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number]; +export type CommitHash = string; export type Path = string[][]; diff --git a/packages/coln-store/src/commit/hash.rs b/packages/coln-store/src/commit/hash.rs index ad0e3e67..37465165 100644 --- a/packages/coln-store/src/commit/hash.rs +++ b/packages/coln-store/src/commit/hash.rs @@ -12,6 +12,7 @@ pub(crate) const HASH_SIZE: usize = 32; #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize, Type)] pub struct CommitHash( #[serde(with = "hex::serde")] + #[specta(type = String)] pub [u8; HASH_SIZE] ); From eeddd2b2b31c1c217b6fbdc3972feaa64e2670a2 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Fri, 4 Sep 2026 15:17:17 +0100 Subject: [PATCH 26/42] sketch out the interface --- packages/coln-rpc/src/{ => rust}/api.rs | 0 packages/coln-rpc/src/{ => rust}/lib.rs | 0 packages/coln-rpc/src/rust/state_machine.rs | 0 packages/coln-rpc/src/typescript/store.ts | 16 ++++++++++++++++ packages/coln-rpc/{ => src/typescript}/types.ts | 0 5 files changed, 16 insertions(+) rename packages/coln-rpc/src/{ => rust}/api.rs (100%) rename packages/coln-rpc/src/{ => rust}/lib.rs (100%) create mode 100644 packages/coln-rpc/src/rust/state_machine.rs create mode 100644 packages/coln-rpc/src/typescript/store.ts rename packages/coln-rpc/{ => src/typescript}/types.ts (100%) diff --git a/packages/coln-rpc/src/api.rs b/packages/coln-rpc/src/rust/api.rs similarity index 100% rename from packages/coln-rpc/src/api.rs rename to packages/coln-rpc/src/rust/api.rs diff --git a/packages/coln-rpc/src/lib.rs b/packages/coln-rpc/src/rust/lib.rs similarity index 100% rename from packages/coln-rpc/src/lib.rs rename to packages/coln-rpc/src/rust/lib.rs diff --git a/packages/coln-rpc/src/rust/state_machine.rs b/packages/coln-rpc/src/rust/state_machine.rs new file mode 100644 index 00000000..e69de29b diff --git a/packages/coln-rpc/src/typescript/store.ts b/packages/coln-rpc/src/typescript/store.ts new file mode 100644 index 00000000..f40d0447 --- /dev/null +++ b/packages/coln-rpc/src/typescript/store.ts @@ -0,0 +1,16 @@ +import {WhereClause, WireRowId, Value, Path, CommitHash} from "./types.js" + +export type WireValue = Value + +export type WireTuple = WireValue[] + +export interface Store { + commit(): CommitHash + abort(): null + + all(query: WhereClause, select: [number]): [WireTuple] + one(query: WhereClause, select: [number]): WireTuple + exists(query: WhereClause): boolean + + add(table_name: Path, values: WireTuple): WireRowId +} diff --git a/packages/coln-rpc/types.ts b/packages/coln-rpc/src/typescript/types.ts similarity index 100% rename from packages/coln-rpc/types.ts rename to packages/coln-rpc/src/typescript/types.ts From a535eaa795e13be3ad37db7cb81ddd4d6999a87e Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Mon, 7 Sep 2026 10:17:15 +0100 Subject: [PATCH 27/42] formatting and clippy fixup --- Cargo.toml | 1 + packages/coln-rpc/Cargo.toml | 3 +++ packages/coln-rpc/scripts/export.rs | 2 +- packages/coln-store/src/commit/hash.rs | 10 ++++++---- packages/coln-store/src/table/cell.rs | 9 +++++---- packages/coln-store/src/txn/row_handle.rs | 2 +- packages/coln-store/src/value.rs | 2 +- 7 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9328edda..61fb7bda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ members = [ "packages/coln-batch", "packages/coln-rpc" ] +resolver = "3" [workspace.package] version = "0.0.1" diff --git a/packages/coln-rpc/Cargo.toml b/packages/coln-rpc/Cargo.toml index fa89984a..92860ee2 100644 --- a/packages/coln-rpc/Cargo.toml +++ b/packages/coln-rpc/Cargo.toml @@ -16,6 +16,9 @@ specta.workspace = true specta-serde = "0.0.12" specta-typescript = { version = "0.0.12", features = ["serde"] } +[lib] +path = "src/rust/lib.rs" + [[bin]] name = "export" path = "scripts/export.rs" diff --git a/packages/coln-rpc/scripts/export.rs b/packages/coln-rpc/scripts/export.rs index 4b9ac761..55b7b3a6 100644 --- a/packages/coln-rpc/scripts/export.rs +++ b/packages/coln-rpc/scripts/export.rs @@ -1,6 +1,6 @@ +use coln_rpc::api::*; use specta::Types; use specta_typescript::Typescript; -use coln_rpc::api::*; fn main() { let mut types = Types::default(); diff --git a/packages/coln-store/src/commit/hash.rs b/packages/coln-store/src/commit/hash.rs index 37465165..3d9b50f5 100644 --- a/packages/coln-store/src/commit/hash.rs +++ b/packages/coln-store/src/commit/hash.rs @@ -2,18 +2,20 @@ // // SPDX-License-Identifier: Apache-2.0 OR MIT -use std::fmt; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use specta::Type; +use std::fmt; /// The number of bytes in a commit hash. pub(crate) const HASH_SIZE: usize = 32; -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize, Type)] +#[derive( + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize, Type, +)] pub struct CommitHash( #[serde(with = "hex::serde")] #[specta(type = String)] - pub [u8; HASH_SIZE] + pub [u8; HASH_SIZE], ); impl CommitHash { diff --git a/packages/coln-store/src/table/cell.rs b/packages/coln-store/src/table/cell.rs index 609f9a04..48d47667 100644 --- a/packages/coln-store/src/table/cell.rs +++ b/packages/coln-store/src/table/cell.rs @@ -2,9 +2,9 @@ // // SPDX-License-Identifier: Apache-2.0 OR MIT -use std::fmt; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use specta::Type; +use std::fmt; use crate::column_map::ColIndex; use crate::commit::hash::CommitHash; @@ -13,11 +13,12 @@ use crate::value::Value; use super::ValidationError; - /// The unique id that identifies each row in a table. /// /// It is managed by the database and read-only for the user. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize, Type)] +#[derive( + Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize, Type, +)] pub struct WireRowId { pub commit: CommitHash, pub counter: u32, diff --git a/packages/coln-store/src/txn/row_handle.rs b/packages/coln-store/src/txn/row_handle.rs index 0f22473a..80e75c06 100644 --- a/packages/coln-store/src/txn/row_handle.rs +++ b/packages/coln-store/src/txn/row_handle.rs @@ -4,7 +4,7 @@ use std::{cell::RefCell, rc::Rc}; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use specta::Type; use crate::{ diff --git a/packages/coln-store/src/value.rs b/packages/coln-store/src/value.rs index 32bcf2a1..aab17f67 100644 --- a/packages/coln-store/src/value.rs +++ b/packages/coln-store/src/value.rs @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2026 Coln contributors // // SPDX-License-Identifier: Apache-2.0 OR MIT -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use specta::Type; #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize, Type)] From 470c4a8e999cdd778eecc6ca34da901ac0d6c425 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Mon, 7 Sep 2026 10:29:06 +0100 Subject: [PATCH 28/42] fix licenses --- packages/coln-rpc/scripts/export.rs | 4 ++++ packages/coln-rpc/src/rust/api.rs | 6 +++++- packages/coln-rpc/src/rust/lib.rs | 4 ++++ packages/coln-rpc/src/rust/state_machine.rs | 3 +++ packages/coln-rpc/src/typescript/store.ts | 4 ++++ packages/coln-rpc/src/typescript/types.ts | 4 ++++ 6 files changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/coln-rpc/scripts/export.rs b/packages/coln-rpc/scripts/export.rs index 55b7b3a6..e78616df 100644 --- a/packages/coln-rpc/scripts/export.rs +++ b/packages/coln-rpc/scripts/export.rs @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 Coln contributors +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + use coln_rpc::api::*; use specta::Types; use specta_typescript::Typescript; diff --git a/packages/coln-rpc/src/rust/api.rs b/packages/coln-rpc/src/rust/api.rs index 86f48261..ea2291e4 100644 --- a/packages/coln-rpc/src/rust/api.rs +++ b/packages/coln-rpc/src/rust/api.rs @@ -1,8 +1,12 @@ +// SPDX-FileCopyrightText: 2026 Coln contributors +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + use coln_flir_rs::ir; use serde::{Deserialize, Serialize}; use specta::Type; // use coln_store::id_packer::IdPacker; -use coln_store::{table::{WireValue}, txn::TxnWireRowId}; +use coln_store::{table::WireValue, txn::TxnWireRowId}; #[derive(Type, Serialize, Deserialize)] #[serde(tag = "type")] diff --git a/packages/coln-rpc/src/rust/lib.rs b/packages/coln-rpc/src/rust/lib.rs index e5fdf85e..00fc022c 100644 --- a/packages/coln-rpc/src/rust/lib.rs +++ b/packages/coln-rpc/src/rust/lib.rs @@ -1 +1,5 @@ +// SPDX-FileCopyrightText: 2026 Coln contributors +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + pub mod api; diff --git a/packages/coln-rpc/src/rust/state_machine.rs b/packages/coln-rpc/src/rust/state_machine.rs index e69de29b..c6932f3d 100644 --- a/packages/coln-rpc/src/rust/state_machine.rs +++ b/packages/coln-rpc/src/rust/state_machine.rs @@ -0,0 +1,3 @@ +// SPDX-FileCopyrightText: 2026 Coln contributors +// +// SPDX-License-Identifier: Apache-2.0 OR MIT diff --git a/packages/coln-rpc/src/typescript/store.ts b/packages/coln-rpc/src/typescript/store.ts index f40d0447..78fbe104 100644 --- a/packages/coln-rpc/src/typescript/store.ts +++ b/packages/coln-rpc/src/typescript/store.ts @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 Coln contributors +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + import {WhereClause, WireRowId, Value, Path, CommitHash} from "./types.js" export type WireValue = Value diff --git a/packages/coln-rpc/src/typescript/types.ts b/packages/coln-rpc/src/typescript/types.ts index 785bc0e2..36db2d9f 100644 --- a/packages/coln-rpc/src/typescript/types.ts +++ b/packages/coln-rpc/src/typescript/types.ts @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 Coln contributors +// +// SPDX-License-Identifier: Apache-2.0 OR MIT + // This file has been generated by Specta. Do not edit this file manually. export type CommitHash = string; From 399ef70f9cc3c73bebc9dc81c54dad80ae5243c9 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Mon, 7 Sep 2026 17:44:26 +0100 Subject: [PATCH 29/42] thinking about runtime system --- .../coln-compiler/typescript-model/graph.ts | 0 .../typescript-model/runtime/flatten.ts | 5 ++ .../typescript-model/runtime/row_id.ts | 29 +++++++++++ .../typescript-model/runtime/set.ts | 16 +++++++ .../typescript-model/runtime/store.ts | 16 +++++++ .../typescript-model/runtime/types.ts | 24 ++++++++++ packages/coln-rpc/scripts/export.rs | 8 +++- packages/coln-rpc/src/rust/api.rs | 48 +------------------ packages/coln-store/src/txn/row_handle.rs | 2 +- 9 files changed, 98 insertions(+), 50 deletions(-) create mode 100644 packages/coln-compiler/typescript-model/graph.ts create mode 100644 packages/coln-compiler/typescript-model/runtime/flatten.ts create mode 100644 packages/coln-compiler/typescript-model/runtime/row_id.ts create mode 100644 packages/coln-compiler/typescript-model/runtime/set.ts create mode 100644 packages/coln-compiler/typescript-model/runtime/store.ts create mode 100644 packages/coln-compiler/typescript-model/runtime/types.ts diff --git a/packages/coln-compiler/typescript-model/graph.ts b/packages/coln-compiler/typescript-model/graph.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/coln-compiler/typescript-model/runtime/flatten.ts b/packages/coln-compiler/typescript-model/runtime/flatten.ts new file mode 100644 index 00000000..2f52298a --- /dev/null +++ b/packages/coln-compiler/typescript-model/runtime/flatten.ts @@ -0,0 +1,5 @@ +import { WireTuple } from "./store"; + +export class Adaptor { + constructor(public flatten: (value: T) => WireTuple, public reconstruct: (tuple: WireTuple) => T) {} +} diff --git a/packages/coln-compiler/typescript-model/runtime/row_id.ts b/packages/coln-compiler/typescript-model/runtime/row_id.ts new file mode 100644 index 00000000..86e0959e --- /dev/null +++ b/packages/coln-compiler/typescript-model/runtime/row_id.ts @@ -0,0 +1,29 @@ +import { CommitHash, TxnWireRowId, WireRowId } from "./types.js"; + +export class RowId { + constructor(private rowId: TxnWireRowId, readonly brand: S) {} + + asWire(): WireRowId { + if (this.rowId.type == "Existing") { + return this.rowId.value + } else if (this.rowId.type == "Pending") { + throw "Must commit before using this row id in a query" + } else { + throw "Unknown row id type" + } + } + + asTxnWire(): TxnWireRowId { + return this.rowId + } + + finish(commit: CommitHash) { + if (this.rowId.type == "Pending") { + const counter = this.rowId.value + this.rowId = { + type: "Existing", + value: {commit, counter} + } + } + } +} diff --git a/packages/coln-compiler/typescript-model/runtime/set.ts b/packages/coln-compiler/typescript-model/runtime/set.ts new file mode 100644 index 00000000..ebe7b6c8 --- /dev/null +++ b/packages/coln-compiler/typescript-model/runtime/set.ts @@ -0,0 +1,16 @@ +import { Store, WireTuple } from "./store.js"; +import { WhereClause } from "./types.js" +import { Adaptor } from "./flatten.js" + +export class View { + constructor( + private store: Store, + private table_name: WhereClause, + private params: WireTuple, + private adapter: Adaptor + ) {} + + // values(): T[] { + // return this.store.all(this.where, this.select).map(this.reconstruct) + // } +} diff --git a/packages/coln-compiler/typescript-model/runtime/store.ts b/packages/coln-compiler/typescript-model/runtime/store.ts new file mode 100644 index 00000000..f40d0447 --- /dev/null +++ b/packages/coln-compiler/typescript-model/runtime/store.ts @@ -0,0 +1,16 @@ +import {WhereClause, WireRowId, Value, Path, CommitHash} from "./types.js" + +export type WireValue = Value + +export type WireTuple = WireValue[] + +export interface Store { + commit(): CommitHash + abort(): null + + all(query: WhereClause, select: [number]): [WireTuple] + one(query: WhereClause, select: [number]): WireTuple + exists(query: WhereClause): boolean + + add(table_name: Path, values: WireTuple): WireRowId +} diff --git a/packages/coln-compiler/typescript-model/runtime/types.ts b/packages/coln-compiler/typescript-model/runtime/types.ts new file mode 100644 index 00000000..7d978ec1 --- /dev/null +++ b/packages/coln-compiler/typescript-model/runtime/types.ts @@ -0,0 +1,24 @@ +// This file has been generated by Specta. Do not edit this file manually. +export type CommitHash = string; + +export type Path = string[][]; + +/** A temporary row ID that is valid only within a transaction. */ +export type TempRowId = number; + +/** A reference to an existing row or a pending row in the current transaction. */ +export type TxnWireRowId = { type: "Existing"; value: WireRowId } | { type: "Pending"; value: TempRowId }; + +export type Value = I | number | string; + +export type WhereClause = { type: "PrimaryKey"; values: Value[] } | { type: "ExceptRowId"; values: Value[] } | { type: "Generic"; values_at: ([number, Value])[] }; + +/** + * The unique id that identifies each row in a table. + * + * It is managed by the database and read-only for the user. + */ +export type WireRowId = { + commit: CommitHash, + counter: number, +}; diff --git a/packages/coln-rpc/scripts/export.rs b/packages/coln-rpc/scripts/export.rs index e78616df..b8fae835 100644 --- a/packages/coln-rpc/scripts/export.rs +++ b/packages/coln-rpc/scripts/export.rs @@ -2,15 +2,19 @@ // // SPDX-License-Identifier: Apache-2.0 OR MIT +use coln_flir_rs::ir::Path; use coln_rpc::api::*; +use coln_store::{table::WireValue, txn::TxnWireValue}; use specta::Types; use specta_typescript::Typescript; fn main() { let mut types = Types::default(); - types.register_mut::(); - types.register_mut::(); + types.register_mut::(); + types.register_mut::(); + types.register_mut::(); + types.register_mut::(); Typescript::default() .export_to("./types.ts", &types, specta_serde::Format) diff --git a/packages/coln-rpc/src/rust/api.rs b/packages/coln-rpc/src/rust/api.rs index ea2291e4..360f1a9a 100644 --- a/packages/coln-rpc/src/rust/api.rs +++ b/packages/coln-rpc/src/rust/api.rs @@ -1,12 +1,8 @@ -// SPDX-FileCopyrightText: 2026 Coln contributors -// -// SPDX-License-Identifier: Apache-2.0 OR MIT - use coln_flir_rs::ir; use serde::{Deserialize, Serialize}; use specta::Type; // use coln_store::id_packer::IdPacker; -use coln_store::{table::WireValue, txn::TxnWireRowId}; +use coln_store::{table::{WireValue}, txn::TxnWireRowId}; #[derive(Type, Serialize, Deserialize)] #[serde(tag = "type")] @@ -15,45 +11,3 @@ pub enum WhereClause { ExceptRowId { values: Vec }, Generic { values_at: Vec<(u32, WireValue)> }, } - -#[derive(Type, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum SelectClause { - All { columns: Vec }, - One { columns: Vec }, - Existence, -} - -#[derive(Type, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum Query { - SelectWhere { - table_name: ir::Path, - select: SelectClause, - r#where: WhereClause, - }, -} - -#[derive(Type, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum QueryResponse { - All { tuples: Vec> }, - One { values: Vec }, - Present, - Absent, -} - -#[derive(Type, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum Mutation { - Insert { - table_name: ir::Path, - columns: Vec, - }, -} - -#[derive(Type, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum MutationResponse { - Id(TxnWireRowId), -} diff --git a/packages/coln-store/src/txn/row_handle.rs b/packages/coln-store/src/txn/row_handle.rs index 80e75c06..4df931ce 100644 --- a/packages/coln-store/src/txn/row_handle.rs +++ b/packages/coln-store/src/txn/row_handle.rs @@ -189,7 +189,7 @@ impl From for TempRowId { /// A reference to an existing row or a pending row in the current transaction. #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Type)] -#[serde(tag = "type")] +#[serde(tag = "type", content = "value")] pub enum TxnWireRowId { Existing(WireRowId), Pending(TempRowId), From dff5e776858c09ba8345ce1fce214d7414bec663 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Mon, 7 Sep 2026 18:41:09 +0100 Subject: [PATCH 30/42] fixed up pipeline to create views for definitions --- packages/coln-cli/app/Coln/CLI/GenerateIR.hs | 8 +++--- packages/coln-cli/app/Coln/CLI/GenerateTS.hs | 10 +++---- .../src/Coln/Backend/TypeScript/Generate.hs | 4 +-- packages/coln-compiler/src/Coln/FLIR/Value.hs | 4 ++- .../coln-compiler/src/Coln/MIR/Interpret.hs | 2 +- packages/coln-compiler/src/Coln/MIR/Params.hs | 6 +++++ packages/coln-compiler/src/Coln/MIR/Top.hs | 26 ++++++++++++++----- packages/coln-compiler/src/Coln/MIR/Value.hs | 2 +- packages/coln-compiler/src/Coln/SIR/Top.hs | 12 ++++----- .../test/golden/graph-of-graphs.coln | 5 ---- .../test/golden/graph-views.coln | 23 ++++++++++++++++ 11 files changed, 69 insertions(+), 33 deletions(-) create mode 100644 packages/coln-compiler/test/golden/graph-views.coln diff --git a/packages/coln-cli/app/Coln/CLI/GenerateIR.hs b/packages/coln-cli/app/Coln/CLI/GenerateIR.hs index 71a3c13d..0858806f 100644 --- a/packages/coln-cli/app/Coln/CLI/GenerateIR.hs +++ b/packages/coln-cli/app/Coln/CLI/GenerateIR.hs @@ -4,12 +4,10 @@ module Coln.CLI.GenerateIR where -import Coln.Backend.Lower -import Coln.CLI.Common +import Coln.Top import Coln.CLI.Options generateIR :: GenerateIROptions -> IO () generateIR opts = do - ge <- loadFile opts.inputFile - writeIRFor ge opts.outputDir - pure () + (rep, realms) <- loadRealms opts.inputFile + writeFLIR opts.outputDir rep realms diff --git a/packages/coln-cli/app/Coln/CLI/GenerateTS.hs b/packages/coln-cli/app/Coln/CLI/GenerateTS.hs index ab05203f..86796507 100644 --- a/packages/coln-cli/app/Coln/CLI/GenerateTS.hs +++ b/packages/coln-cli/app/Coln/CLI/GenerateTS.hs @@ -4,12 +4,12 @@ module Coln.CLI.GenerateTS where -import Coln.Backend.TypeScript.Generate -import Coln.CLI.Common +-- import Coln.Backend.TypeScript.Generate +-- import Coln.CLI.Common import Coln.CLI.Options generateTS :: GenerateTSOptions -> IO () generateTS opts = do - ge <- loadFile opts.inputFile - generate ge opts.outputDir - pure () + putStrLn "typescript generation currently unimplemented" + -- ge <- loadFile opts.inputFile + -- generate ge opts.outputDir diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs index f2f46598..72632638 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs @@ -204,9 +204,9 @@ genEl :: Access -> TSEnv -> SIR.El l -> TS.El genEl access e = \case SIR.LiftEl t -> genEl access e t SIR.Var i -> elemAt e.tsLocals i - SIR.Single q -> TS.MethodCall (genQuery access e q) "single" [] + -- SIR.Single q -> TS.MethodCall (genQuery access e q) "single" [] SIR.Proj t x -> TS.Proj (genEl access e t) (mangle x) - SIR.Multi _ q -> TS.MethodCall (genQuery access e q) "multi" [] + -- SIR.Multi _ q -> TS.MethodCall (genQuery access e q) "multi" [] SIR.Lam _dom abs -> do let (x, body) = genAbs access e abs TS.Lam diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs index 0b3cac39..021ac0b7 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Value.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -231,7 +231,9 @@ toNotationTerm _ (Param (FId _)) = panic "param" toNotationAtom :: OMap TableName [ColName] -> [ColName] -> Atom -> N.Ntn0 toNotationAtom columnNames cs a = do let entity = toNotationTop a.entity - let cols = fromJust (OMap.lookup a.entity columnNames) + let cols = case OMap.lookup a.entity columnNames of + Just cols -> cols + Nothing -> panic $ show a.entity ++ " not found" let field (i, t) = N.Infix (toNotationColName (cols !! i)) (N.Keyword "↦" ()) (toNotationTerm cs t) let body = N.Juxt entity $ N.Tuple (map field . mapMaybe sequence $ zip [0 ..] a.values) () case a.rowId of diff --git a/packages/coln-compiler/src/Coln/MIR/Interpret.hs b/packages/coln-compiler/src/Coln/MIR/Interpret.hs index 458b2455..a4778e62 100644 --- a/packages/coln-compiler/src/Coln/MIR/Interpret.hs +++ b/packages/coln-compiler/src/Coln/MIR/Interpret.hs @@ -52,7 +52,7 @@ instance Interp S.El V.El where S.Proj l t0 x -> withLevel l.mlevel $ \sl -> do let v = interpAt sl g e t0 Pair sl (V.proj v x) - S.Init _ -> panic "cannot interpret init yet" + S.Init a -> Pair STheory $ V.Describe $ V.Init (interpAt STheory g e a) S.Lit l -> Pair SSet (V.Lit l) S.Is t -> case interp g e t of Pair l v -> Pair l (V.Become v) diff --git a/packages/coln-compiler/src/Coln/MIR/Params.hs b/packages/coln-compiler/src/Coln/MIR/Params.hs index 017401ff..7ad18ae5 100644 --- a/packages/coln-compiler/src/Coln/MIR/Params.hs +++ b/packages/coln-compiler/src/Coln/MIR/Params.hs @@ -8,6 +8,12 @@ data SMLevel :: MLevel -> Type where STheory :: SMLevel Theory STop :: SMLevel Top +instance Show (SMLevel l) where + show = \case + SSet -> "SSet" + STheory -> "STheory" + STop -> "STop" + withLevel :: MLevel -> (forall l. SMLevel l -> a) -> a withLevel l f = case l of Set -> f SSet diff --git a/packages/coln-compiler/src/Coln/MIR/Top.hs b/packages/coln-compiler/src/Coln/MIR/Top.hs index 72205c80..e0270c38 100644 --- a/packages/coln-compiler/src/Coln/MIR/Top.hs +++ b/packages/coln-compiler/src/Coln/MIR/Top.hs @@ -16,20 +16,32 @@ import Coln.Core.Readback import Coln.MIR.Interpret import Coln.MIR.Layout import Coln.MIR.Memoed qualified as M -import Coln.MIR.Params (SMLevel (..), levelCoerce) +import Coln.MIR.Params (SMLevel (..)) import Coln.MIR.Realm as MIR import Coln.MIR.Value qualified as V +evalToNominative :: V.Description V.El l -> V.El N l +evalToNominative = \case + V.Describe v -> toNominative v + V.Become v -> v + +toNominative :: V.El D l -> V.El N l +toNominative = \case + V.LiftEl l v -> V.LiftEl l (toNominative v) + V.Init _ -> panic "init not allowed in globals" + V.Lam fv a clo -> do + let clo' = case clo of + V.Clo x f -> V.Clo x (evalToNominative . f) + V.CloConst v -> V.CloConst (evalToNominative v) + V.Lam fv a clo' + V.Cons fields -> V.Cons $ evalToNominative <$> fields + interpGlobals :: Core.Globals -> V.Globals interpGlobals g = foldl go OMap.empty $ OMap.assocs g.definitions where interp' :: V.Globals -> Name -> Core.Definition Global -> Match SMLevel (V.El N) - interp' acc x def = case interp acc BwdNil def.body.stx of - Pair l decl -> do - let declT = V.emap (levelCoerce l STheory) decl - let nomT = snd $ declareEvaluation (BwdNil :> x) (emptyScope "shouldNeverBeUsed") declT - let nom = levelCoerce STheory l nomT.val - Pair l nom + interp' acc _ def = case interp acc BwdNil def.body.stx of + Pair l v -> Pair l (evalToNominative v) go :: V.Globals -> (Name, Core.Definition Global) -> V.Globals go acc (x, def) = acc OMap.>| (x, interp' acc x def) diff --git a/packages/coln-compiler/src/Coln/MIR/Value.hs b/packages/coln-compiler/src/Coln/MIR/Value.hs index b2dec620..3ec73a5f 100644 --- a/packages/coln-compiler/src/Coln/MIR/Value.hs +++ b/packages/coln-compiler/src/Coln/MIR/Value.hs @@ -79,7 +79,7 @@ instance LevelCoerce (El c) where levelCoerce STheory SSet (LiftEl LSetTheory v) = v levelCoerce STop STheory (LiftEl LTheoryTop v) = v levelCoerce STop SSet (LiftEl LTheoryTop (LiftEl LSetTheory v)) = v - levelCoerce _ _ _ = panic "cannot level coerce" + levelCoerce sl0 sl1 _ = panic $ "cannot level coerce from " ++ show sl0 ++ " to " ++ show sl1 data FunctionType (l0 :: MLevel) (l1 :: MLevel) = FunctionType { variant :: SFunctionVariant l0 l1 diff --git a/packages/coln-compiler/src/Coln/SIR/Top.hs b/packages/coln-compiler/src/Coln/SIR/Top.hs index e6603c43..d5ffafd7 100644 --- a/packages/coln-compiler/src/Coln/SIR/Top.hs +++ b/packages/coln-compiler/src/Coln/SIR/Top.hs @@ -29,11 +29,11 @@ split3 d = do (d1, d2, d3) aggregate3 :: - (TableName -> a -> (Maybe (Trie x), Maybe (Trie y), Maybe (Trie z))) -> - (TableName -> Trie a -> (Maybe (Trie x), Maybe (Trie y), Maybe (Trie z))) -aggregate3 f t (Leaf a) = f t a -aggregate3 f t (Node d) = do - let (d1, d2, d3) = split3 $ aggregate3 f t <$> d + (Path -> a -> (Maybe (Trie x), Maybe (Trie y), Maybe (Trie z))) -> + (Path -> Trie a -> (Maybe (Trie x), Maybe (Trie y), Maybe (Trie z))) +aggregate3 f p (Leaf a) = f p a +aggregate3 f p (Node d) = do + let (d1, d2, d3) = split3 $ mapWithKey (\x -> aggregate3 f (p :> x)) d (Node <$> d1, Node <$> d2, Node <$> d3) cleanTrie :: Trie a -> Maybe (Trie a) @@ -50,7 +50,7 @@ fromNode (Just (Node d)) = toList d mirToSIR :: RealmId -> MIR.Realm -> SIR.Realm mirToSIR rId r = do let (_, _, root) = cache "root" (BwdNil :> "root") (emptyScope rId) r.root - let (rootE, rootD, rootR) = aggregate3 separateGenerator (TableName rId $ BwdNil) r.generators + let (rootE, rootD, rootR) = aggregate3 (\p -> separateGenerator (TableName rId p)) BwdNil r.generators let (names, cached) = unzip $ map (fst &&& uncurry (cacheTop rId)) $ OMap.assocs r.realmDefinitions let (cachedE, cachedD, _) = unzip3 cached let viewE = Node $ fromList [(x, y) | (x, Just y) <- zip names (map cleanTrie cachedE)] diff --git a/packages/coln-compiler/test/golden/graph-of-graphs.coln b/packages/coln-compiler/test/golden/graph-of-graphs.coln index 460f310c..bd526790 100644 --- a/packages/coln-compiler/test/golden/graph-of-graphs.coln +++ b/packages/coln-compiler/test/golden/graph-of-graphs.coln @@ -4,11 +4,6 @@ theory Graph := sig end realm GraphRealm @ Graph - def free-edge : Set := sig - v0 : self.V - v1 : self.V - f : self.E v0 v1 - end end theory Graph/hom (G0 : Graph) (G1 : Graph) := sig diff --git a/packages/coln-compiler/test/golden/graph-views.coln b/packages/coln-compiler/test/golden/graph-views.coln new file mode 100644 index 00000000..96c5c3b9 --- /dev/null +++ b/packages/coln-compiler/test/golden/graph-views.coln @@ -0,0 +1,23 @@ +theory Graph := sig + V : Set + E : V -> V -> Set +end + +theory TransExt (^i G : Graph) := sig + connected : G.V -> G.V -> Prop + refl : (v : G.V) -> connected v v + snoc : (v0 : G.V) -> (v1 : G.V) -> (v2 : G.V) -> connected v0 v1 -> G.E v1 v2 -> connected v0 v2 +end + +realm GraphRealm @ Graph + def triangle : Set := sig + a : root.V + b : root.V + c : root.V + f : root.E a b + g : root.E b c + h : root.E a c + end + + ind def trans-closure : TransExt root := init (TransExt root) +end From 3309afaee15af01be61a0c7fad3eb89e7176e777 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Tue, 8 Sep 2026 09:33:20 +0100 Subject: [PATCH 31/42] antecedents -> arguments --- packages/coln-compiler/src/Coln/FLIR/Value.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs index 021ac0b7..cd3a07e0 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Value.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -156,7 +156,7 @@ instance AE.ToJSON Definition where [ AE.pair "vars" $ AE.list (AE.list id . (\(x, y) -> [x, y]) . (SIR.encPath *** AE.toEncoding)) $ r.vars , AE.pair "antecedents" $ AE.toEncoding r.antecedents , AE.pair "definand" $ SIR.encPath r.definand - , AE.pair "antecedents" $ AE.toEncoding r.args + , AE.pair "arguments" $ AE.toEncoding r.args ] instance AE.ToJSON Rule where From 989535951f56cb5cc96e256e7d8adf302558a4c6 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Tue, 8 Sep 2026 10:15:51 +0100 Subject: [PATCH 32/42] examples --- packages/coln-compiler/test/golden/flow-expr.coln | 15 +++++++++++++++ .../{graph-views.coln => transitive-closure.coln} | 9 --------- packages/coln-compiler/test/golden/triangle.coln | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 packages/coln-compiler/test/golden/flow-expr.coln rename packages/coln-compiler/test/golden/{graph-views.coln => transitive-closure.coln} (72%) create mode 100644 packages/coln-compiler/test/golden/triangle.coln diff --git a/packages/coln-compiler/test/golden/flow-expr.coln b/packages/coln-compiler/test/golden/flow-expr.coln new file mode 100644 index 00000000..983f8aec --- /dev/null +++ b/packages/coln-compiler/test/golden/flow-expr.coln @@ -0,0 +1,15 @@ +theory Graph := sig + vertex : Set + edge : vertex -> vertex -> Set +end + +theory FlowExpr/motive (^i G : Graph) := sig + t : G.vertex -> Set + const : (v : G.vertex) -> Int -> t v + plus : (v : G.vertex) -> t v -> t v -> t v + flow : (from : G.vertex) -> (into : G.vertex) -> G.edge from into -> t into +end + +realm GraphRealm @ Graph + ind def FlowExpr : FlowExpr/motive root := init (FlowExpr/motive root) +end diff --git a/packages/coln-compiler/test/golden/graph-views.coln b/packages/coln-compiler/test/golden/transitive-closure.coln similarity index 72% rename from packages/coln-compiler/test/golden/graph-views.coln rename to packages/coln-compiler/test/golden/transitive-closure.coln index 96c5c3b9..8cbe2b7c 100644 --- a/packages/coln-compiler/test/golden/graph-views.coln +++ b/packages/coln-compiler/test/golden/transitive-closure.coln @@ -10,14 +10,5 @@ theory TransExt (^i G : Graph) := sig end realm GraphRealm @ Graph - def triangle : Set := sig - a : root.V - b : root.V - c : root.V - f : root.E a b - g : root.E b c - h : root.E a c - end - ind def trans-closure : TransExt root := init (TransExt root) end diff --git a/packages/coln-compiler/test/golden/triangle.coln b/packages/coln-compiler/test/golden/triangle.coln new file mode 100644 index 00000000..510534cb --- /dev/null +++ b/packages/coln-compiler/test/golden/triangle.coln @@ -0,0 +1,15 @@ +theory Graph := sig + V : Set + E : V -> V -> Set +end + +realm GraphRealm @ Graph + def triangle : Set := sig + a : root.V + b : root.V + c : root.V + f : root.E a b + g : root.E b c + h : root.E a c + end +end From 749d89cd845381328528bdba19b279d8f3c8451e Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Tue, 8 Sep 2026 10:54:02 +0100 Subject: [PATCH 33/42] updated coln-flir-rs for new flir --- packages/coln-flir-rs/src/ir/mod.rs | 35 +++++++++++++-------- packages/coln-query/src/api/query.rs | 16 +++++----- packages/coln-query/src/test_utils.rs | 14 ++++----- packages/coln-store/src/commit/wire/root.rs | 8 ++--- packages/coln-store/src/solver/bind.rs | 28 ++++++++--------- packages/coln-store/src/solver/compile.rs | 34 ++++++++++---------- packages/coln-store/src/solver/validate.rs | 28 ++++++++--------- packages/coln-store/src/store/tests.rs | 13 ++++---- 8 files changed, 92 insertions(+), 84 deletions(-) diff --git a/packages/coln-flir-rs/src/ir/mod.rs b/packages/coln-flir-rs/src/ir/mod.rs index 75d39ebd..72b34e94 100644 --- a/packages/coln-flir-rs/src/ir/mod.rs +++ b/packages/coln-flir-rs/src/ir/mod.rs @@ -149,7 +149,7 @@ pub enum Lit { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "tag", rename_all = "lowercase")] -pub enum Term { +pub enum El { Lit { lit: Lit }, Var { index: VarIdx }, } @@ -157,7 +157,7 @@ pub enum Term { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ValueEntry { pub column: ColumnIdx, - pub term: Term, + pub term: El, } /// An [`Atom`] references an entity (a relation or a table) to bring some of @@ -171,7 +171,7 @@ pub struct Atom { /// /// Note: A [`Some(Term::Lit)`](Term::Lit) does not make sense in this /// context, as we do not support a row id literal at the moment, I suppose. - pub row_id: Option, + pub row_id: Option, /// To bring some columns of the [`Entity`](Self::entity) into scope. pub values: Vec, } @@ -192,8 +192,8 @@ pub enum Prop { /// we assert `left == right`. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Equality { - pub left: Term, - pub right: Term, + pub left: El, + pub right: El, } #[derive(Debug, Copy, Clone, Serialize, Deserialize)] @@ -215,20 +215,23 @@ pub enum RuleVariant { #[serde(rename_all = "camelCase")] pub struct Rule { pub rule_variant: RuleVariant, - /// Assigns some names to the variables the rule binds. - /// - /// Note: Must be of the same arity as [`Self::var_types`]. - pub var_names: Vec, - /// Tells the types of the variables the rule binds. - /// - /// Note: Must be of the same arity as [`Self::var_names`]. - pub var_types: Vec, + /// The variables the rule binds. + pub vars: Vec<(ColName, ColType)>, /// The left-hand side of the implication. pub antecedents: Vec, /// The right-hand side of the implication. pub consequents: Vec, } +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Definition { + pub vars: Vec<(ColName, ColType)>, + pub antecedents: Vec, + pub definand: Path, + pub args: Vec +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TableEntry { /// The "name" of the table. @@ -237,6 +240,7 @@ pub struct TableEntry { pub table: Schema, } + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RuleEntry { /// The "name" of the rule. @@ -245,6 +249,11 @@ pub struct RuleEntry { pub rule: Rule, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DefinitionEntry { + +} + /// The top-level type of a flattened realm and the starting point of the FLIR. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FlatRealm { diff --git a/packages/coln-query/src/api/query.rs b/packages/coln-query/src/api/query.rs index 8e094e07..3ba238ab 100644 --- a/packages/coln-query/src/api/query.rs +++ b/packages/coln-query/src/api/query.rs @@ -22,7 +22,7 @@ use crate::relational::expr::{ use crate::relational::schema::{Column, EntityRef, TableSchema}; use crate::scalarial::ScalarType; use coln_flir_rs::ir::{ - self, Atom, EntityVariant, Equality, FlatRealm, Path, Prop, RuleEntry, TableEntry, Term, + self, Atom, EntityVariant, Equality, FlatRealm, Path, Prop, RuleEntry, TableEntry, El, }; use coln_flir_rs::schema::{ BaseTableSchema, CompilerColIdx, NativeScalarType, QueryEngineCol, QueryEngineScalarType, @@ -362,7 +362,7 @@ impl FlirProgram { // The row id, if this atom brings it into scope. if let Some(row_id) = &atom.row_id { match row_id { - ir::Term::Var { index } => { + ir::El::Var { index } => { let var = friendly_var(vars, *index)?; if !var.is_row_id() { return Err(SyntaxError::new( @@ -375,7 +375,7 @@ impl FlirProgram { schema.resolve_query_cols(CompilerColIdx::for_row_id()), )?; } - ir::Term::Lit { lit: _ } => { + ir::El::Lit { lit: _ } => { // Matching [`ir::Atom::row_id`]'s own note: a literal row id // is not something we can express. return Err(SyntaxError::new( @@ -389,7 +389,7 @@ impl FlirProgram { for value in &atom.values { let mut columns = schema.resolve_query_cols(CompilerColIdx::from(value.column)); match &value.term { - ir::Term::Lit { lit } => { + ir::El::Lit { lit } => { let column = columns.next().ok_or_else(|| { SyntaxError::new("FLIR compares a literal against a column that does not resolve to any query column") })?; @@ -399,7 +399,7 @@ impl FlirProgram { right: Expr::from(LiteralExpr::from(Literal::from(lit))), })); } - ir::Term::Var { index } => { + ir::El::Var { index } => { binder.bind(*index, friendly_var(vars, *index)?, columns)?; } } @@ -433,10 +433,10 @@ impl FlirProgram { bindings: binder.bindings, }) } - fn term(&mut self, term: &Term, vars: &[FriendlyVar]) -> Result, SyntaxError> { + fn term(&mut self, term: &El, vars: &[FriendlyVar]) -> Result, SyntaxError> { match term { - Term::Lit { lit } => Ok(vec![Expr::from(LiteralExpr::from(Literal::from(lit)))]), - Term::Var { index } => Ok(friendly_var(vars, *index)? + El::Lit { lit } => Ok(vec![Expr::from(LiteralExpr::from(Literal::from(lit)))]), + El::Var { index } => Ok(friendly_var(vars, *index)? .parts() .map(|(_part, name)| Expr::from(VarExpr::new(name))) .collect()), diff --git a/packages/coln-query/src/test_utils.rs b/packages/coln-query/src/test_utils.rs index 7fac9b24..8cfe99e4 100644 --- a/packages/coln-query/src/test_utils.rs +++ b/packages/coln-query/src/test_utils.rs @@ -102,8 +102,8 @@ pub mod flir { /// constraining the columns named by index in `values`. pub fn atom( entity: &str, - row_id: Option, - values: Vec<(ir::ColumnIdx, ir::Term)>, + row_id: Option, + values: Vec<(ir::ColumnIdx, ir::El)>, ) -> ir::Atom { ir::Atom { entity: ir::Path::from(entity), @@ -127,19 +127,19 @@ pub mod flir { } } - pub fn var_term(index: ir::VarIdx) -> ir::Term { - ir::Term::Var { index } + pub fn var_term(index: ir::VarIdx) -> ir::El { + ir::El::Var { index } } - pub fn lit_term(value: i64) -> ir::Term { - ir::Term::Lit { + pub fn lit_term(value: i64) -> ir::El { + ir::El::Lit { lit: ir::Lit::Int { value: value.try_into().unwrap(), }, } } - pub fn equality(left: ir::Term, right: ir::Term) -> ir::Equality { + pub fn equality(left: ir::El, right: ir::El) -> ir::Equality { ir::Equality { left, right } } } diff --git a/packages/coln-store/src/commit/wire/root.rs b/packages/coln-store/src/commit/wire/root.rs index e9847add..dc50d5f6 100644 --- a/packages/coln-store/src/commit/wire/root.rs +++ b/packages/coln-store/src/commit/wire/root.rs @@ -21,7 +21,7 @@ mod tests { use super::*; use crate::ir::{ Atom, BuiltinTy, ColType, ColumnEntry, EntityVariant, Path, Prop, Rule, RuleEntry, - RuleVariant, Schema, TableEntry, Term, ValueEntry, + RuleVariant, Schema, TableEntry, El, ValueEntry, }; fn int_schema() -> Schema { @@ -73,14 +73,14 @@ mod tests { row_id: None, values: vec![ValueEntry { column: 0, - term: Term::Var { index: 0 }, + term: El::Var { index: 0 }, }], }, }], consequents: vec![Prop::Eq { equality: Equality { - left: Term::Var { index: 0 }, - right: Term::Var { index: 0 }, + left: El::Var { index: 0 }, + right: El::Var { index: 0 }, }, }], }, diff --git a/packages/coln-store/src/solver/bind.rs b/packages/coln-store/src/solver/bind.rs index 74500a9c..16fc3c0e 100644 --- a/packages/coln-store/src/solver/bind.rs +++ b/packages/coln-store/src/solver/bind.rs @@ -221,11 +221,11 @@ mod tests { values: vec![ ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }, ir::ValueEntry { column: 1, - term: ir::Term::Var { index: 1 }, + term: ir::El::Var { index: 1 }, }, ], }, @@ -237,11 +237,11 @@ mod tests { values: vec![ ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 1 }, + term: ir::El::Var { index: 1 }, }, ir::ValueEntry { column: 1, - term: ir::Term::Var { index: 2 }, + term: ir::El::Var { index: 2 }, }, ], }, @@ -253,7 +253,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }], }, }], @@ -298,7 +298,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }], }, }, @@ -308,14 +308,14 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 1 }, + term: ir::El::Var { index: 1 }, }], }, }, ir::Prop::Eq { equality: Equality { - left: ir::Term::Var { index: 0 }, - right: ir::Term::Var { index: 1 }, + left: ir::El::Var { index: 0 }, + right: ir::El::Var { index: 1 }, }, }, ], @@ -325,7 +325,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }], }, }], @@ -354,14 +354,14 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }], }, }, ir::Prop::Eq { equality: Equality { - left: ir::Term::Var { index: 0 }, - right: ir::Term::Lit { + left: ir::El::Var { index: 0 }, + right: ir::El::Lit { lit: ir::Lit::Int { value: 2 }, }, }, @@ -373,7 +373,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }], }, }], diff --git a/packages/coln-store/src/solver/compile.rs b/packages/coln-store/src/solver/compile.rs index 9067d9b9..81519ed5 100644 --- a/packages/coln-store/src/solver/compile.rs +++ b/packages/coln-store/src/solver/compile.rs @@ -4,7 +4,7 @@ use std::{collections::HashSet, fmt}; -use crate::ir::{self, Atom, Prop, RuleEntry, Term}; +use crate::ir::{self, Atom, Prop, RuleEntry, El}; /// Errors raised while lowering an `ir::Rule` into the restricted solver form. #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] @@ -185,9 +185,9 @@ fn compile_atom(atom: &Atom, var_count: usize) -> Result }) } -fn compile_term(term: &Term, var_count: usize) -> Result { +fn compile_term(term: &El, var_count: usize) -> Result { match term { - Term::Var { index } => { + El::Var { index } => { if *index >= var_count as u64 { return Err(CompileError::InvalidVarIndex { index: *index, @@ -196,7 +196,7 @@ fn compile_term(term: &Term, var_count: usize) -> Result } Ok(CompTerm::Var(*index as usize)) } - Term::Lit { lit } => Ok(CompTerm::Lit(lit.clone())), + El::Lit { lit } => Ok(CompTerm::Lit(lit.clone())), } } @@ -380,7 +380,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: Term::Var { index: 0 }, + term: El::Var { index: 0 }, }], }, }], @@ -390,7 +390,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: Term::Var { index: 0 }, + term: El::Var { index: 0 }, }], }, }], @@ -526,8 +526,8 @@ mod tests { vec![int_ty(), int_ty()], vec![Prop::Eq { equality: Equality { - left: Term::Var { index: 0 }, - right: Term::Var { index: 1 }, + left: El::Var { index: 0 }, + right: El::Var { index: 1 }, }, }], vec![Prop::Atom { @@ -557,19 +557,19 @@ mod tests { values: vec![ ir::ValueEntry { column: 0, - term: Term::Var { index: 0 }, + term: El::Var { index: 0 }, }, ir::ValueEntry { column: 1, - term: Term::Var { index: 1 }, + term: El::Var { index: 1 }, }, ], }, }], vec![Prop::Eq { equality: Equality { - left: Term::Var { index: 0 }, - right: Term::Var { index: 1 }, + left: El::Var { index: 0 }, + right: El::Var { index: 1 }, }, }], ); @@ -602,11 +602,11 @@ mod tests { values: vec![ ir::ValueEntry { column: 0, - term: Term::Var { index: 0 }, + term: El::Var { index: 0 }, }, ir::ValueEntry { column: 1, - term: Term::Var { index: 1 }, + term: El::Var { index: 1 }, }, ], }, @@ -618,14 +618,14 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: Term::Var { index: 0 }, + term: El::Var { index: 0 }, }], }, }, Prop::Eq { equality: Equality { - left: Term::Var { index: 0 }, - right: Term::Var { index: 1 }, + left: El::Var { index: 0 }, + right: El::Var { index: 1 }, }, }, ], diff --git a/packages/coln-store/src/solver/validate.rs b/packages/coln-store/src/solver/validate.rs index a8e01eed..a730da18 100644 --- a/packages/coln-store/src/solver/validate.rs +++ b/packages/coln-store/src/solver/validate.rs @@ -259,7 +259,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }], }, }], @@ -269,7 +269,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }], }, }], @@ -305,11 +305,11 @@ mod tests { values: vec![ ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }, ir::ValueEntry { column: 1, - term: ir::Term::Var { index: 1 }, + term: ir::El::Var { index: 1 }, }, ], }, @@ -321,7 +321,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }], }, }, @@ -331,7 +331,7 @@ mod tests { row_id: None, values: vec![ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 1 }, + term: ir::El::Var { index: 1 }, }], }, }, @@ -388,19 +388,19 @@ mod tests { values: vec![ ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }, ir::ValueEntry { column: 1, - term: ir::Term::Var { index: 1 }, + term: ir::El::Var { index: 1 }, }, ], }, }], vec![ir::Prop::Eq { equality: Equality { - left: ir::Term::Var { index: 0 }, - right: ir::Term::Var { index: 1 }, + left: ir::El::Var { index: 0 }, + right: ir::El::Var { index: 1 }, }, }], ); @@ -430,19 +430,19 @@ mod tests { values: vec![ ir::ValueEntry { column: 0, - term: ir::Term::Var { index: 0 }, + term: ir::El::Var { index: 0 }, }, ir::ValueEntry { column: 1, - term: ir::Term::Var { index: 1 }, + term: ir::El::Var { index: 1 }, }, ], }, }], vec![ir::Prop::Eq { equality: Equality { - left: ir::Term::Var { index: 0 }, - right: ir::Term::Var { index: 1 }, + left: ir::El::Var { index: 0 }, + right: ir::El::Var { index: 1 }, }, }], ); diff --git a/packages/coln-store/src/store/tests.rs b/packages/coln-store/src/store/tests.rs index 8f0d172b..82032a64 100644 --- a/packages/coln-store/src/store/tests.rs +++ b/packages/coln-store/src/store/tests.rs @@ -6,7 +6,7 @@ pub(crate) mod test_support { use crate::ir::{ Atom, BuiltinTy, ColType, ColumnEntry, EntityVariant, FlatRealm, Path, Prop, Rule, - RuleEntry, RuleVariant, Schema, TableEntry, Term, ValueEntry, + RuleEntry, RuleVariant, Schema, TableEntry, El, ValueEntry, }; fn int_col_type() -> ColType { @@ -52,8 +52,7 @@ pub(crate) mod test_support { path: Path::from("Link.foreignKeys"), rule: Rule { rule_variant: RuleVariant::Enforced, - var_names: vec![Path::from("a"), Path::from("b")], - var_types: vec![int_col_type(), int_col_type()], + vars: vec![(Path::from("a"), int_col_type()), (Path::from("b"), int_col_type())], antecedents: vec![Prop::Atom { atom: Atom { entity: link.clone(), @@ -61,11 +60,11 @@ pub(crate) mod test_support { values: vec![ ValueEntry { column: 0, - term: Term::Var { index: 0 }, + term: El::Var { index: 0 }, }, ValueEntry { column: 1, - term: Term::Var { index: 1 }, + term: El::Var { index: 1 }, }, ], }, @@ -77,7 +76,7 @@ pub(crate) mod test_support { row_id: None, values: vec![ValueEntry { column: 0, - term: Term::Var { index: 0 }, + term: El::Var { index: 0 }, }], }, }, @@ -87,7 +86,7 @@ pub(crate) mod test_support { row_id: None, values: vec![ValueEntry { column: 0, - term: Term::Var { index: 1 }, + term: El::Var { index: 1 }, }], }, }, From 47aae653f67961b12d80a8add562e20b2ae314b9 Mon Sep 17 00:00:00 2001 From: Leo Stewen Date: Tue, 8 Sep 2026 13:11:25 +0200 Subject: [PATCH 34/42] [coln-query & coln-flir-rs] fix: enable parsing of updated FLIR again minus issue of missing column indices --- packages/coln-flir-rs/src/ir/mod.rs | 18 +- packages/coln-flir-rs/src/schema.rs | 9 +- .../tests/data/GraphOfGraphsRealm.json | 899 ++++++++++++++++++ .../tests/data/GraphOfGraphsRealm.pretty | 105 ++ .../coln-flir-rs/tests/data/GraphRealm.json | 103 ++ .../coln-flir-rs/tests/data/GraphRealm.pretty | 15 + packages/coln-flir-rs/tests/test_theory.rs | 7 +- packages/coln-query/src/api/mod.rs | 2 + packages/coln-query/src/api/query.rs | 23 +- packages/coln-query/src/test_utils.rs | 11 +- 10 files changed, 1151 insertions(+), 41 deletions(-) create mode 100644 packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json create mode 100644 packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.pretty create mode 100644 packages/coln-flir-rs/tests/data/GraphRealm.json create mode 100644 packages/coln-flir-rs/tests/data/GraphRealm.pretty diff --git a/packages/coln-flir-rs/src/ir/mod.rs b/packages/coln-flir-rs/src/ir/mod.rs index 72b34e94..e41bf232 100644 --- a/packages/coln-flir-rs/src/ir/mod.rs +++ b/packages/coln-flir-rs/src/ir/mod.rs @@ -20,8 +20,7 @@ pub struct Path(pub Vec); /// A column name is given by a [`Path`]. pub type ColName = Path; -/// An index into the [`varNames`](Rule::var_names) and -/// [`varTypes`](Rule::var_types) arrays of a [`Rule`]. +/// An index into the [`vars`](Rule::vars) array of a [`Rule`]. /// /// Note: An `FId` in `coln-compiler`. pub type VarIdx = u64; @@ -134,7 +133,7 @@ pub struct Schema { /// `ColB`. /// /// At the moment there is only support for a single (compound) primary key. - pub primary_key: Option>, + pub primary_key: Option>, } /// A literal expression. @@ -169,8 +168,8 @@ pub struct Atom { pub entity: Path, /// To bring the `row_id` of the [`Entity`](Self::entity) into scope. /// - /// Note: A [`Some(Term::Lit)`](Term::Lit) does not make sense in this - /// context, as we do not support a row id literal at the moment, I suppose. + /// Note: A [`Some(El::Lit)`](El::Lit) does not make sense in this context, + /// as we do not support a row id literal at the moment, I suppose. pub row_id: Option, /// To bring some columns of the [`Entity`](Self::entity) into scope. pub values: Vec, @@ -229,7 +228,7 @@ pub struct Definition { pub vars: Vec<(ColName, ColType)>, pub antecedents: Vec, pub definand: Path, - pub args: Vec + pub args: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -240,7 +239,6 @@ pub struct TableEntry { pub table: Schema, } - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RuleEntry { /// The "name" of the rule. @@ -250,9 +248,7 @@ pub struct RuleEntry { } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DefinitionEntry { - -} +pub struct DefinitionEntry {} /// The top-level type of a flattened realm and the starting point of the FLIR. #[derive(Debug, Clone, Serialize, Deserialize)] @@ -260,6 +256,8 @@ pub struct FlatRealm { /// The tables of the flattened realm. #[serde(rename = "entities")] pub tables: Vec, + /// How derived views are computed. These contain the chased laws. + pub definitions: Vec, /// The rules (laws) of the flattened realm. pub rules: Vec, } diff --git a/packages/coln-flir-rs/src/schema.rs b/packages/coln-flir-rs/src/schema.rs index ede59de2..712c8f71 100644 --- a/packages/coln-flir-rs/src/schema.rs +++ b/packages/coln-flir-rs/src/schema.rs @@ -121,14 +121,7 @@ impl From<&ir::TableEntry> for Option { .map_or(Vec::new(), |compound_primary_key| { compound_primary_key .iter() - .map(|primary_key_column| { - schema - .columns - .iter() - .position(|column| column.path == *primary_key_column) - .map(|idx| CompilerColIdx::Column(idx as u64)) - .unwrap_or_else(|| panic!("Primary key column {primary_key_column} not found in base table {path}")) - }) + .map(|primary_key_column| CompilerColIdx::Column(*primary_key_column)) .collect::>() }); // Currently, the compiler supports only a single primary key. diff --git a/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json b/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json new file mode 100644 index 00000000..5fe98495 --- /dev/null +++ b/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json @@ -0,0 +1,899 @@ +{ + "entities": [ + { + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [], + "primaryKey": null + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + } + ], + "primaryKey": null + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + } + ], + "primaryKey": null + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + }, + { + "path": [["c"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + } + ], + "primaryKey": null + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["v0"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["v1"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + }, + { + "path": [["V"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + } + ], + "primaryKey": [0, 1, 2, 3] + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["v0"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["v1"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + }, + { + "path": [["v0", "a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + }, + { + "path": [["v1", "a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + }, + { + "path": [["E"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + } + ], + "primaryKey": [0, 1, 2, 3, 4, 5] + } + } + ], + "definitions": [], + "rules": [ + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["base"], + ["V"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": null, + "values": [] + } + } + ], + "consequents": [] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["base"], + ["E"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": null, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + } + ] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["fiber"], + ["V"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": null, + "values": [{ "tag": "var", "index": 0 }] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + } + ] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["fiber"], + ["E"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["c"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "rowId": null, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 }, + { "tag": "var", "index": 2 } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [{ "tag": "var", "index": 0 }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [{ "tag": "var", "index": 0 }] + } + } + ] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["action"], + ["V"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["v0"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["v1"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["V"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "rowId": null, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 }, + { "tag": "var", "index": 2 }, + { "tag": "var", "index": 3 }, + { "tag": "var", "index": 4 } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [{ "tag": "var", "index": 0 }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 4 }, + "values": [{ "tag": "var", "index": 1 }] + } + } + ] + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"], ["total"]], + "value": { + "ruleVariant": "monitored", + "vars": [ + [ + [["v0"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["v1"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [{ "tag": "var", "index": 0 }] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "rowId": null, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 }, + { "tag": "var", "index": 2 }, + { "tag": "var", "index": 3 } + ] + } + } + ] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["action"], + ["E"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["v0"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["v1"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + ], + [ + [["v0", "a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["v1", "a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + ], + [ + [["E"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + ], + [ + [["c"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["d"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"]], + "rowId": null, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 }, + { "tag": "var", "index": 2 }, + { "tag": "var", "index": 3 }, + { "tag": "var", "index": 4 }, + { "tag": "var", "index": 5 }, + { "tag": "var", "index": 6 } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [{ "tag": "var", "index": 0 }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 4 }, + "values": [{ "tag": "var", "index": 0 }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "rowId": { "tag": "var", "index": 5 }, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 3 }, + { "tag": "var", "index": 4 } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "rowId": null, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 }, + { "tag": "var", "index": 2 }, + { "tag": "var", "index": 3 }, + { "tag": "var", "index": 7 } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "rowId": null, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 }, + { "tag": "var", "index": 2 }, + { "tag": "var", "index": 4 }, + { "tag": "var", "index": 8 } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "rowId": { "tag": "var", "index": 6 }, + "values": [ + { "tag": "var", "index": 1 }, + { "tag": "var", "index": 7 }, + { "tag": "var", "index": 8 } + ] + } + } + ] + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"], ["total"]], + "value": { + "ruleVariant": "monitored", + "vars": [ + [ + [["v0"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["v1"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + ], + [ + [["v0", "a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["v1", "a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [{ "tag": "var", "index": 0 }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 4 }, + "values": [{ "tag": "var", "index": 0 }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "rowId": { "tag": "var", "index": 5 }, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 3 }, + { "tag": "var", "index": 4 } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"]], + "rowId": null, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 }, + { "tag": "var", "index": 2 }, + { "tag": "var", "index": 3 }, + { "tag": "var", "index": 4 }, + { "tag": "var", "index": 5 } + ] + } + } + ] + } + } + ] +} diff --git a/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.pretty b/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.pretty new file mode 100644 index 00000000..2db79b44 --- /dev/null +++ b/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.pretty @@ -0,0 +1,105 @@ +flatrealm + entities + table ℜ.root.base.V := [] + table ℜ.root.base.E := [.a : ℜ.root.base.V, .b : ℜ.root.base.V] + table ℜ.root.fiber.V := [.a : ℜ.root.base.V] + table ℜ.root.fiber.E := [ + .a : ℜ.root.base.V, + .b : ℜ.root.fiber.V, + .c : ℜ.root.fiber.V + ] + table ℜ.root.action.V := [ + .v0 : ℜ.root.base.V, + .v1 : ℜ.root.base.V, + .a : ℜ.root.base.E, + .b : ℜ.root.fiber.V, + .V : ℜ.root.fiber.V + ] primarykey [.v0, .v1, .a, .b] + table ℜ.root.action.E := [ + .v0 : ℜ.root.base.V, + .v1 : ℜ.root.base.V, + .a : ℜ.root.base.E, + .v0/a : ℜ.root.fiber.V, + .v1/a : ℜ.root.fiber.V, + .b : ℜ.root.fiber.E, + .E : ℜ.root.fiber.E + ] primarykey [.v0, .v1, .a, .v0/a, .v1/a, .b] + end + definitions + end + rules + enforced ℜ.root.base.V.foreignKey := ℜ.root.base.V [] ⊢ ⊤ + enforced ℜ.root.base.E.foreignKey a b := ℜ.root.base.E [ + .a ↦ a, + .b ↦ b + ] ⊢ a ∈ ℜ.root.base.V [] ∧ b ∈ ℜ.root.base.V [] + enforced ℜ.root.fiber.V.foreignKey a := ℜ.root.fiber.V [ + .a ↦ a + ] ⊢ a ∈ ℜ.root.base.V [] + enforced ℜ.root.fiber.E.foreignKey a b c := ℜ.root.fiber.E [ + .a ↦ a, + .b ↦ b, + .c ↦ c + ] ⊢ a ∈ ℜ.root.base.V [] ∧ b ∈ ℜ.root.fiber.V [ + .a ↦ a + ] ∧ c ∈ ℜ.root.fiber.V [.a ↦ a] + enforced ℜ.root.action.V.foreignKey v0 v1 a b V := ℜ.root.action.V [ + .v0 ↦ v0, + .v1 ↦ v1, + .a ↦ a, + .b ↦ b, + .V ↦ V + ] ⊢ v0 ∈ ℜ.root.base.V [] ∧ v1 ∈ ℜ.root.base.V [] ∧ a ∈ ℜ.root.base.E [ + .a ↦ v0, + .b ↦ v1 + ] ∧ b ∈ ℜ.root.fiber.V [.a ↦ v0] ∧ V ∈ ℜ.root.fiber.V [.a ↦ v1] + monitored ℜ.root.action.V.total v0 v1 a b := v0 ∈ ℜ.root.base.V [] ∧ v1 ∈ ℜ.root.base.V [] ∧ a ∈ ℜ.root.base.E [ + .a ↦ v0, + .b ↦ v1 + ] ∧ b ∈ ℜ.root.fiber.V [.a ↦ v0] ⊢ ℜ.root.action.V [ + .v0 ↦ v0, + .v1 ↦ v1, + .a ↦ a, + .b ↦ b + ] + enforced ℜ.root.action.E.foreignKey v0 v1 a v0/a v1/a b E c d := ℜ.root.action.E [ + .v0 ↦ v0, + .v1 ↦ v1, + .a ↦ a, + .v0/a ↦ v0/a, + .v1/a ↦ v1/a, + .b ↦ b, + .E ↦ E + ] ⊢ v0 ∈ ℜ.root.base.V [] ∧ v1 ∈ ℜ.root.base.V [] ∧ a ∈ ℜ.root.base.E [ + .a ↦ v0, + .b ↦ v1 + ] ∧ v0/a ∈ ℜ.root.fiber.V [.a ↦ v0] ∧ v1/a ∈ ℜ.root.fiber.V [ + .a ↦ v0 + ] ∧ b ∈ ℜ.root.fiber.E [.a ↦ v0, .b ↦ v0/a, .c ↦ v1/a] ∧ ℜ.root.action.V [ + .v0 ↦ v0, + .v1 ↦ v1, + .a ↦ a, + .b ↦ v0/a, + .V ↦ c + ] ∧ ℜ.root.action.V [ + .v0 ↦ v0, + .v1 ↦ v1, + .a ↦ a, + .b ↦ v1/a, + .V ↦ d + ] ∧ E ∈ ℜ.root.fiber.E [.a ↦ v1, .b ↦ c, .c ↦ d] + monitored ℜ.root.action.E.total v0 v1 a v0/a v1/a b := v0 ∈ ℜ.root.base.V [] ∧ v1 ∈ ℜ.root.base.V [] ∧ a ∈ ℜ.root.base.E [ + .a ↦ v0, + .b ↦ v1 + ] ∧ v0/a ∈ ℜ.root.fiber.V [.a ↦ v0] ∧ v1/a ∈ ℜ.root.fiber.V [ + .a ↦ v0 + ] ∧ b ∈ ℜ.root.fiber.E [.a ↦ v0, .b ↦ v0/a, .c ↦ v1/a] ⊢ ℜ.root.action.E [ + .v0 ↦ v0, + .v1 ↦ v1, + .a ↦ a, + .v0/a ↦ v0/a, + .v1/a ↦ v1/a, + .b ↦ b + ] + end +end \ No newline at end of file diff --git a/packages/coln-flir-rs/tests/data/GraphRealm.json b/packages/coln-flir-rs/tests/data/GraphRealm.json new file mode 100644 index 00000000..2dbf1c4e --- /dev/null +++ b/packages/coln-flir-rs/tests/data/GraphRealm.json @@ -0,0 +1,103 @@ +{ + "entities": [ + { + "path": [["GraphRealm"], ["root"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [], + "primaryKey": null + } + }, + { + "path": [["GraphRealm"], ["root"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphRealm"], ["root"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphRealm"], ["root"], ["V"]] + } + } + ], + "primaryKey": null + } + } + ], + "definitions": [], + "rules": [ + { + "path": [["GraphRealm"], ["root"], ["V"], ["foreignKey"]], + "value": { + "ruleVariant": "enforced", + "vars": [], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphRealm"], ["root"], ["V"]], + "rowId": null, + "values": [] + } + } + ], + "consequents": [] + } + }, + { + "path": [["GraphRealm"], ["root"], ["E"], ["foreignKey"]], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { "tag": "rowId", "path": [["GraphRealm"], ["root"], ["V"]] } + ], + [ + [["b"]], + { "tag": "rowId", "path": [["GraphRealm"], ["root"], ["V"]] } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphRealm"], ["root"], ["E"]], + "rowId": null, + "values": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + } + ] + } + } + ] +} diff --git a/packages/coln-flir-rs/tests/data/GraphRealm.pretty b/packages/coln-flir-rs/tests/data/GraphRealm.pretty new file mode 100644 index 00000000..e9386260 --- /dev/null +++ b/packages/coln-flir-rs/tests/data/GraphRealm.pretty @@ -0,0 +1,15 @@ +flatrealm + entities + table ℜ.root.V := [] + table ℜ.root.E := [.a : ℜ.root.V, .b : ℜ.root.V] + end + definitions + end + rules + enforced ℜ.root.V.foreignKey := ℜ.root.V [] ⊢ ⊤ + enforced ℜ.root.E.foreignKey a b := ℜ.root.E [ + .a ↦ a, + .b ↦ b + ] ⊢ a ∈ ℜ.root.V [] ∧ b ∈ ℜ.root.V [] + end +end \ No newline at end of file diff --git a/packages/coln-flir-rs/tests/test_theory.rs b/packages/coln-flir-rs/tests/test_theory.rs index 9fe42086..5838cf80 100644 --- a/packages/coln-flir-rs/tests/test_theory.rs +++ b/packages/coln-flir-rs/tests/test_theory.rs @@ -6,7 +6,7 @@ use coln_flir_rs::ir::Path; use coln_flir_rs::test_utils; // TODO add more theory json files -const THEORY_FIXTURES: &[&str] = &["Graph.json", "Prim.json"]; +const THEORY_FIXTURES: &[&str] = &["GraphOfGraphsRealm.json", "GraphRealm.json"]; #[test] fn deserialises_all_theory_fixtures() { @@ -17,7 +17,7 @@ fn deserialises_all_theory_fixtures() { #[test] fn deserialises_graph_theory() { - let theory = test_utils::load_theory_from_json("Graph.json"); + let theory = test_utils::load_theory_from_json("GraphRealm.json"); assert_eq!(theory.tables.len(), 2); assert_eq!(theory.rules.len(), 2); @@ -27,6 +27,5 @@ fn deserialises_graph_theory() { let rules = &theory.rules[0]; assert_eq!(rules.path, Path::from("Graph.E.foreignKey")); - assert_eq!(rules.rule.var_names.len(), 2); - assert_eq!(rules.rule.var_types.len(), 2); + assert_eq!(rules.rule.vars.len(), 2); } diff --git a/packages/coln-query/src/api/mod.rs b/packages/coln-query/src/api/mod.rs index 062e7ac2..c05d5ac7 100644 --- a/packages/coln-query/src/api/mod.rs +++ b/packages/coln-query/src/api/mod.rs @@ -241,6 +241,7 @@ mod test { fn main_usage() -> Result<(), Error> { let flat_realm = FlatRealm { tables: vec![], + definitions: vec![], rules: vec![], }; let mut coln_query = ColnQuery::init(&flat_realm)?; @@ -293,6 +294,7 @@ mod test { fn restart_usage() -> Result<(), Error> { let flat_realm = FlatRealm { tables: vec![], + definitions: vec![], rules: vec![], }; let mut coln_query = ColnQuery::init(&flat_realm)?; diff --git a/packages/coln-query/src/api/query.rs b/packages/coln-query/src/api/query.rs index 3ba238ab..0d3c6716 100644 --- a/packages/coln-query/src/api/query.rs +++ b/packages/coln-query/src/api/query.rs @@ -22,7 +22,7 @@ use crate::relational::expr::{ use crate::relational::schema::{Column, EntityRef, TableSchema}; use crate::scalarial::ScalarType; use coln_flir_rs::ir::{ - self, Atom, EntityVariant, Equality, FlatRealm, Path, Prop, RuleEntry, TableEntry, El, + self, Atom, El, EntityVariant, Equality, FlatRealm, Path, Prop, RuleEntry, TableEntry, }; use coln_flir_rs::schema::{ BaseTableSchema, CompilerColIdx, NativeScalarType, QueryEngineCol, QueryEngineScalarType, @@ -499,10 +499,10 @@ impl QueryProgram for FlirProgram { /// /// 1. Meaningless rules with an empty [consequent](ir::Rule::consequents) are /// skipped and chased rules panic at the moment due to open questions. -/// 2. It zips the [`ir::Rule::var_names`] and the [`ir::Rule::var_types`] into one -/// array of [`FriendlyVar`]s. -/// 3. It converts [`ir::Rule::antecedents`] and [`ir::Rule::consequents`] into a -/// [`ConjunctiveQuery`], each. +/// 2. It creates the wrapper type [`FriendlyVar`]s for a rule's +/// [`ir::Rule::vars`]. +/// 3. It converts [`ir::Rule::antecedents`] and [`ir::Rule::consequents`] into +/// a [`ConjunctiveQuery`], each. struct FriendlyRule { kind: ir::RuleVariant, vars: Vec, @@ -520,14 +520,9 @@ impl FriendlyRule { "[Unclear] Chased rules produce a materialized view; how are they different from a materialized view defined in the table/entities section?" ); } - assert!( - rule.var_names.len() == rule.var_types.len(), - "var_names and var_types arrays do not size match" - ); let vars = rule - .var_names + .vars .iter() - .zip(rule.var_types.iter()) .map(|(path, col_type)| FriendlyVar { name: path.clone(), ty: col_type.clone(), @@ -571,8 +566,7 @@ impl ConjunctiveQuery { } } -/// All information from [`ir::Rule::var_names`] and [`ir::Rule::var_types`] but -/// _zipped_. +/// A wrapper type around ([`ir::Path`], [`ir::ColType`]). struct FriendlyVar { name: ir::Path, ty: ir::ColType, // either a row id or a builtin type @@ -1074,6 +1068,7 @@ mod tests { T, vec![("a", builtin_int()), ("b", builtin_int())], )], + definitions: vec![], rules: vec![enforced_rule( "r", [("x", builtin_int()), ("y", builtin_int())], @@ -1120,6 +1115,7 @@ mod tests { T, vec![("a", builtin_int()), ("b", builtin_int())], )], + definitions: vec![], rules: vec![enforced_rule( "r", [("x", builtin_int()), ("y", builtin_int())], @@ -1146,6 +1142,7 @@ mod tests { ); let realm = FlatRealm { tables: vec![table_entry(T, vec![("a", builtin_int())])], + definitions: vec![], rules: vec![rule.clone(), rule], }; assert!(FlirProgram::from_flat_realm(&realm).is_err()); diff --git a/packages/coln-query/src/test_utils.rs b/packages/coln-query/src/test_utils.rs index 8cfe99e4..4bd765f2 100644 --- a/packages/coln-query/src/test_utils.rs +++ b/packages/coln-query/src/test_utils.rs @@ -66,16 +66,14 @@ pub mod flir { antecedents: Vec, consequents: Vec, ) -> ir::RuleEntry { - let (var_names, var_types) = vars - .into_iter() - .map(|(name, col_type)| (ir::Path::from(name), col_type)) - .unzip(); ir::RuleEntry { path: ir::Path::from(name), rule: ir::Rule { rule_variant: variant, - var_names, - var_types, + vars: vars + .into_iter() + .map(|(name, col_type)| (ir::Path::from(name), col_type)) + .collect(), antecedents, consequents, }, @@ -169,6 +167,7 @@ pub mod monitored_flir { let x = || vec![(0, flir::var_term(0))]; ir::FlatRealm { tables: vec![flir::table_entry(TABLE, vec![("a", flir::builtin_int())])], + definitions: vec![], rules: vec![flir::rule_entry( RULE, ir::RuleVariant::Monitored, From 357c76765ea6bf4a02c9f3494220668c997430f2 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Wed, 9 Sep 2026 15:50:31 +0100 Subject: [PATCH 35/42] more model code --- .../coln-compiler/typescript-model/graph.ts | 19 ++++++++++++ .../typescript-model/runtime/index.ts | 3 ++ .../typescript-model/runtime/set.ts | 29 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 packages/coln-compiler/typescript-model/runtime/index.ts diff --git a/packages/coln-compiler/typescript-model/graph.ts b/packages/coln-compiler/typescript-model/graph.ts index e69de29b..f056a830 100644 --- a/packages/coln-compiler/typescript-model/graph.ts +++ b/packages/coln-compiler/typescript-model/graph.ts @@ -0,0 +1,19 @@ +import * as runtime from "./runtime/index.js" + +function todo(): T { + throw "todo" +} + +export class GraphRealm { + root: { + vertex: runtime.MutableSet>, + edge: (src: runtime.RowId<"root.vertex">) => (tgt: runtime.RowId<"root.vertex">) => runtime.MutableSet> + } + + constructor(store: runtime.Store) { + this.root = { + vertex: new runtime.BoundBaseTable(store, [["root"], ["vertex"]], []), + edge: todo() + }; + } +} diff --git a/packages/coln-compiler/typescript-model/runtime/index.ts b/packages/coln-compiler/typescript-model/runtime/index.ts new file mode 100644 index 00000000..18084c4b --- /dev/null +++ b/packages/coln-compiler/typescript-model/runtime/index.ts @@ -0,0 +1,3 @@ +export { RowId } from "./row_id.js" +export { Store } from "./store.js" +export { Set, MutableSet, BoundBaseTable } from "./set.js" diff --git a/packages/coln-compiler/typescript-model/runtime/set.ts b/packages/coln-compiler/typescript-model/runtime/set.ts index ebe7b6c8..368585d6 100644 --- a/packages/coln-compiler/typescript-model/runtime/set.ts +++ b/packages/coln-compiler/typescript-model/runtime/set.ts @@ -2,6 +2,35 @@ import { Store, WireTuple } from "./store.js"; import { WhereClause } from "./types.js" import { Adaptor } from "./flatten.js" +export interface Set { + values(): T[] + contains(value: T): boolean +} + +function todo(): T { + throw "todo" +} + +export interface MutableSet extends Set { + add(): T +} + +export class BoundBaseTable implements MutableSet { + constructor(private store: Store) {} + + values(): T[] { + return todo() + } + + contains(v: T): boolean { + return todo() + } + + add(): T { + return todo() + } +} + export class View { constructor( private store: Store, From ce80ab3174402e07faa7e350d13090289261c792 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Wed, 9 Sep 2026 19:33:30 +0100 Subject: [PATCH 36/42] fixup compatibility between new FLIR and Rust-side crates --- .../coln-compiler/src/Coln/FLIR/Flatten.hs | 4 +- packages/coln-compiler/src/Coln/FLIR/Value.hs | 8 +- packages/coln-flir-rs/src/ir/mod.rs | 14 +- .../tests/data/GraphOfGraphsRealm.json | 900 +----------------- .../coln-flir-rs/tests/data/GraphRealm.json | 104 +- packages/coln-js-runtime/src/rust/handles.rs | 1 + packages/coln-query/src/api/query.rs | 2 +- packages/coln-store/src/commit/graph.rs | 1 + packages/coln-store/src/commit/mod.rs | 8 +- packages/coln-store/src/commit/pst.rs | 1 + packages/coln-store/src/commit/wire/root.rs | 25 +- packages/coln-store/src/repl/exe/mod.rs | 2 +- packages/coln-store/src/solver/bind.rs | 7 +- packages/coln-store/src/solver/compile.rs | 13 +- packages/coln-store/src/solver/validate.rs | 7 +- packages/coln-store/src/store/mod.rs | 2 + packages/coln-store/src/store/tests.rs | 5 +- packages/coln-store/src/table/mod.rs | 22 +- packages/coln-store/src/table/sorted.rs | 2 +- packages/coln-store/src/table/tests.rs | 32 +- packages/coln-store/src/txn/mod.rs | 2 +- packages/coln-store/tests/test_path.rs | 2 +- packages/coln-store/tests/test_subduction.rs | 1 + 23 files changed, 77 insertions(+), 1088 deletions(-) diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index 40da4a04..f8ed630f 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -110,7 +110,7 @@ instance Flatten (S.El Set) Els where S.Lookup tn args shape -> do v <- fresh Nothing shape args' <- traverse (flatten l) args - assert $ single $ V.PAtom $ V.Atom tn Nothing (Just <$> concatEls (args' ++ [v])) + assert $ single $ V.PAtom $ V.Atom tn Nothing (zip [0..] $ concatEls (args' ++ [v])) pure v S.Proj t x -> do v <- flatten l t @@ -132,7 +132,7 @@ instance Flatten S.Prop Props where S.Atom tn t args -> do mv <- asAtomHead <$> flatten l t argvs <- traverse (flatten l) args - pure $ single $ V.PAtom (V.Atom tn mv (Just <$> concatEls argvs)) + pure $ single $ V.PAtom (V.Atom tn mv (zip [0..] $ concatEls argvs)) S.And ps -> mconcat <$> traverse (flatten l) (toList ps.values) S.Eq sh t0 t1 -> do v0 <- flatten l t0 diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs index cd3a07e0..1d2da5be 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Value.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -54,7 +54,7 @@ data El data Atom = Atom { entity :: TableName , rowId :: Maybe El - , values :: [Maybe El] + , values :: [(Int, El)] } deriving (Show, Eq, Generic) @@ -140,7 +140,7 @@ instance AE.ToJSON Atom where mconcat [ AE.pair "entity" $ SIR.encPath a.entity , AE.pair "rowId" $ AE.toEncoding a.rowId - , AE.pair "values" $ AE.toEncoding a.values + , AE.pair "values" $ AE.list (\(i, t) -> AE.pairs $ mconcat [ AE.pair "column" (AE.toEncoding i), AE.pair "term" (AE.toEncoding t) ]) a.values ] instance AE.ToJSON Prop where @@ -235,7 +235,7 @@ toNotationAtom columnNames cs a = do Just cols -> cols Nothing -> panic $ show a.entity ++ " not found" let field (i, t) = N.Infix (toNotationColName (cols !! i)) (N.Keyword "↦" ()) (toNotationTerm cs t) - let body = N.Juxt entity $ N.Tuple (map field . mapMaybe sequence $ zip [0 ..] a.values) () + let body = N.Juxt entity $ N.Tuple (map field a.values) () case a.rowId of Nothing -> body Just r -> N.Infix (toNotationTerm cs r) (N.Keyword "∈" ()) body @@ -254,7 +254,7 @@ toNotationDefinition columnNames (tn, r) = do let keyword = "chased" let head = foldl' N.Juxt (toNotationTop tn) (fmap toNotationTop (map fst r.vars)) let ante = toNotationConjunction $ fmap (toNotationProp columnNames $ map fst r.vars) r.antecedents - let cons = toNotationAtom columnNames (map fst r.vars) $ Atom r.definand Nothing $ map Just r.args + let cons = toNotationAtom columnNames (map fst r.vars) $ Atom r.definand Nothing $ zip [0..] r.args let seq = N.Infix ante (N.Keyword "⊢" ()) cons N.Decl keyword (N.Infix head (N.Keyword ":=" ()) seq) () diff --git a/packages/coln-flir-rs/src/ir/mod.rs b/packages/coln-flir-rs/src/ir/mod.rs index e41bf232..5c184ed5 100644 --- a/packages/coln-flir-rs/src/ir/mod.rs +++ b/packages/coln-flir-rs/src/ir/mod.rs @@ -83,7 +83,7 @@ pub enum ColType { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(tag = "tag", rename_all = "camelCase")] +#[serde(rename_all = "camelCase")] pub enum Materialization { Recomputed, Memoized, @@ -102,7 +102,7 @@ pub enum EntityVariant { /// A base table of the extensional database (EDB). Table, /// A derived view of the intensional database (IDB). - View(Materialization), + View { materialization: Materialization }, /// Tell `coln-store` to create an index and possibly hint to `coln-query`. Index { method: IndexMethod, @@ -228,7 +228,7 @@ pub struct Definition { pub vars: Vec<(ColName, ColType)>, pub antecedents: Vec, pub definand: Path, - pub args: Vec, + pub arguments: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -248,7 +248,11 @@ pub struct RuleEntry { } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DefinitionEntry {} +pub struct DefinitionEntry { + pub path: Path, + #[serde(rename = "value")] + pub definition: Definition, +} /// The top-level type of a flattened realm and the starting point of the FLIR. #[derive(Debug, Clone, Serialize, Deserialize)] @@ -257,7 +261,7 @@ pub struct FlatRealm { #[serde(rename = "entities")] pub tables: Vec, /// How derived views are computed. These contain the chased laws. - pub definitions: Vec, + pub definitions: Vec, /// The rules (laws) of the flattened realm. pub rules: Vec, } diff --git a/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json b/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json index 5fe98495..bc511314 100644 --- a/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json +++ b/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json @@ -1,899 +1 @@ -{ - "entities": [ - { - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [], - "primaryKey": null - } - }, - { - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [ - { - "path": [["a"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - }, - { - "path": [["b"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - } - ], - "primaryKey": null - } - }, - { - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [ - { - "path": [["a"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - } - ], - "primaryKey": null - } - }, - { - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [ - { - "path": [["a"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - }, - { - "path": [["b"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - }, - { - "path": [["c"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - } - ], - "primaryKey": null - } - }, - { - "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [ - { - "path": [["v0"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - }, - { - "path": [["v1"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - }, - { - "path": [["a"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] - } - }, - { - "path": [["b"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - }, - { - "path": [["V"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - } - ], - "primaryKey": [0, 1, 2, 3] - } - }, - { - "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [ - { - "path": [["v0"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - }, - { - "path": [["v1"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - }, - { - "path": [["a"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] - } - }, - { - "path": [["v0", "a"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - }, - { - "path": [["v1", "a"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - }, - { - "path": [["b"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] - } - }, - { - "path": [["E"]], - "type": { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] - } - } - ], - "primaryKey": [0, 1, 2, 3, 4, 5] - } - } - ], - "definitions": [], - "rules": [ - { - "path": [ - ["GraphOfGraphsRealm"], - ["root"], - ["base"], - ["V"], - ["foreignKey"] - ], - "value": { - "ruleVariant": "enforced", - "vars": [], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": null, - "values": [] - } - } - ], - "consequents": [] - } - }, - { - "path": [ - ["GraphOfGraphsRealm"], - ["root"], - ["base"], - ["E"], - ["foreignKey"] - ], - "value": { - "ruleVariant": "enforced", - "vars": [ - [ - [["a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["b"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ] - ], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], - "rowId": null, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 } - ] - } - } - ], - "consequents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 0 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 1 }, - "values": [] - } - } - ] - } - }, - { - "path": [ - ["GraphOfGraphsRealm"], - ["root"], - ["fiber"], - ["V"], - ["foreignKey"] - ], - "value": { - "ruleVariant": "enforced", - "vars": [ - [ - [["a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ] - ], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": null, - "values": [{ "tag": "var", "index": 0 }] - } - } - ], - "consequents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 0 }, - "values": [] - } - } - ] - } - }, - { - "path": [ - ["GraphOfGraphsRealm"], - ["root"], - ["fiber"], - ["E"], - ["foreignKey"] - ], - "value": { - "ruleVariant": "enforced", - "vars": [ - [ - [["a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["b"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ], - [ - [["c"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ] - ], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], - "rowId": null, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 }, - { "tag": "var", "index": 2 } - ] - } - } - ], - "consequents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 0 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": { "tag": "var", "index": 1 }, - "values": [{ "tag": "var", "index": 0 }] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": { "tag": "var", "index": 2 }, - "values": [{ "tag": "var", "index": 0 }] - } - } - ] - } - }, - { - "path": [ - ["GraphOfGraphsRealm"], - ["root"], - ["action"], - ["V"], - ["foreignKey"] - ], - "value": { - "ruleVariant": "enforced", - "vars": [ - [ - [["v0"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["v1"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] - } - ], - [ - [["b"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ], - [ - [["V"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ] - ], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], - "rowId": null, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 }, - { "tag": "var", "index": 2 }, - { "tag": "var", "index": 3 }, - { "tag": "var", "index": 4 } - ] - } - } - ], - "consequents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 0 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 1 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], - "rowId": { "tag": "var", "index": 2 }, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 } - ] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": { "tag": "var", "index": 3 }, - "values": [{ "tag": "var", "index": 0 }] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": { "tag": "var", "index": 4 }, - "values": [{ "tag": "var", "index": 1 }] - } - } - ] - } - }, - { - "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"], ["total"]], - "value": { - "ruleVariant": "monitored", - "vars": [ - [ - [["v0"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["v1"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] - } - ], - [ - [["b"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ] - ], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 0 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 1 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], - "rowId": { "tag": "var", "index": 2 }, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 } - ] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": { "tag": "var", "index": 3 }, - "values": [{ "tag": "var", "index": 0 }] - } - } - ], - "consequents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], - "rowId": null, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 }, - { "tag": "var", "index": 2 }, - { "tag": "var", "index": 3 } - ] - } - } - ] - } - }, - { - "path": [ - ["GraphOfGraphsRealm"], - ["root"], - ["action"], - ["E"], - ["foreignKey"] - ], - "value": { - "ruleVariant": "enforced", - "vars": [ - [ - [["v0"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["v1"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] - } - ], - [ - [["v0", "a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ], - [ - [["v1", "a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ], - [ - [["b"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] - } - ], - [ - [["E"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] - } - ], - [ - [["c"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ], - [ - [["d"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ] - ], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"]], - "rowId": null, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 }, - { "tag": "var", "index": 2 }, - { "tag": "var", "index": 3 }, - { "tag": "var", "index": 4 }, - { "tag": "var", "index": 5 }, - { "tag": "var", "index": 6 } - ] - } - } - ], - "consequents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 0 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 1 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], - "rowId": { "tag": "var", "index": 2 }, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 } - ] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": { "tag": "var", "index": 3 }, - "values": [{ "tag": "var", "index": 0 }] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": { "tag": "var", "index": 4 }, - "values": [{ "tag": "var", "index": 0 }] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], - "rowId": { "tag": "var", "index": 5 }, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 3 }, - { "tag": "var", "index": 4 } - ] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], - "rowId": null, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 }, - { "tag": "var", "index": 2 }, - { "tag": "var", "index": 3 }, - { "tag": "var", "index": 7 } - ] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], - "rowId": null, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 }, - { "tag": "var", "index": 2 }, - { "tag": "var", "index": 4 }, - { "tag": "var", "index": 8 } - ] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], - "rowId": { "tag": "var", "index": 6 }, - "values": [ - { "tag": "var", "index": 1 }, - { "tag": "var", "index": 7 }, - { "tag": "var", "index": 8 } - ] - } - } - ] - } - }, - { - "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"], ["total"]], - "value": { - "ruleVariant": "monitored", - "vars": [ - [ - [["v0"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["v1"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] - } - ], - [ - [["a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] - } - ], - [ - [["v0", "a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ], - [ - [["v1", "a"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] - } - ], - [ - [["b"]], - { - "tag": "rowId", - "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] - } - ] - ], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 0 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], - "rowId": { "tag": "var", "index": 1 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], - "rowId": { "tag": "var", "index": 2 }, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 } - ] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": { "tag": "var", "index": 3 }, - "values": [{ "tag": "var", "index": 0 }] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], - "rowId": { "tag": "var", "index": 4 }, - "values": [{ "tag": "var", "index": 0 }] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], - "rowId": { "tag": "var", "index": 5 }, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 3 }, - { "tag": "var", "index": 4 } - ] - } - } - ], - "consequents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"]], - "rowId": null, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 }, - { "tag": "var", "index": 2 }, - { "tag": "var", "index": 3 }, - { "tag": "var", "index": 4 }, - { "tag": "var", "index": 5 } - ] - } - } - ] - } - } - ] -} +{"entities":[{"path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"value":{"entityVariant":{"tag":"table"},"columns":[],"primaryKey":null}},{"path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}}],"primaryKey":null}},{"path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}}],"primaryKey":null}},{"path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}},{"path":[["c"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}}],"primaryKey":null}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["v0"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["v1"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}},{"path":[["V"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}}],"primaryKey":[0,1,2,3]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["E"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["v0"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["v1"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}},{"path":[["v0","a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}},{"path":[["v1","a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}},{"path":[["E"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}}],"primaryKey":[0,1,2,3,4,5]}}],"definitions":[],"rules":[{"path":[["GraphOfGraphsRealm"],["root"],["base"],["V"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":null,"values":[]}}],"consequents":[]}},{"path":[["GraphOfGraphsRealm"],["root"],["base"],["E"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["c"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":1},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}}]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["V"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["v0"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["v1"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["V"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}},{"column":4,"term":{"tag":"var","index":4}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":3},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":4},"values":[{"column":0,"term":{"tag":"var","index":1}}]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["V"],["total"]],"value":{"ruleVariant":"monitored","vars":[[[["v0"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["v1"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":3},"values":[{"column":0,"term":{"tag":"var","index":0}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}}]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["E"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["v0"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["v1"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}],[[["v0","a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["v1","a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}],[[["E"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}],[[["c"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["d"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}},{"column":4,"term":{"tag":"var","index":4}},{"column":5,"term":{"tag":"var","index":5}},{"column":6,"term":{"tag":"var","index":6}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":3},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":4},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"rowId":{"tag":"var","index":5},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":3}},{"column":2,"term":{"tag":"var","index":4}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}},{"column":4,"term":{"tag":"var","index":7}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":4}},{"column":4,"term":{"tag":"var","index":8}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"rowId":{"tag":"var","index":6},"values":[{"column":0,"term":{"tag":"var","index":1}},{"column":1,"term":{"tag":"var","index":7}},{"column":2,"term":{"tag":"var","index":8}}]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["E"],["total"]],"value":{"ruleVariant":"monitored","vars":[[[["v0"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["v1"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}],[[["v0","a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["v1","a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":3},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":4},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"rowId":{"tag":"var","index":5},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":3}},{"column":2,"term":{"tag":"var","index":4}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}},{"column":4,"term":{"tag":"var","index":4}},{"column":5,"term":{"tag":"var","index":5}}]}}]}}]} \ No newline at end of file diff --git a/packages/coln-flir-rs/tests/data/GraphRealm.json b/packages/coln-flir-rs/tests/data/GraphRealm.json index 2dbf1c4e..b717644c 100644 --- a/packages/coln-flir-rs/tests/data/GraphRealm.json +++ b/packages/coln-flir-rs/tests/data/GraphRealm.json @@ -1,103 +1 @@ -{ - "entities": [ - { - "path": [["GraphRealm"], ["root"], ["V"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [], - "primaryKey": null - } - }, - { - "path": [["GraphRealm"], ["root"], ["E"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [ - { - "path": [["a"]], - "type": { - "tag": "rowId", - "path": [["GraphRealm"], ["root"], ["V"]] - } - }, - { - "path": [["b"]], - "type": { - "tag": "rowId", - "path": [["GraphRealm"], ["root"], ["V"]] - } - } - ], - "primaryKey": null - } - } - ], - "definitions": [], - "rules": [ - { - "path": [["GraphRealm"], ["root"], ["V"], ["foreignKey"]], - "value": { - "ruleVariant": "enforced", - "vars": [], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphRealm"], ["root"], ["V"]], - "rowId": null, - "values": [] - } - } - ], - "consequents": [] - } - }, - { - "path": [["GraphRealm"], ["root"], ["E"], ["foreignKey"]], - "value": { - "ruleVariant": "enforced", - "vars": [ - [ - [["a"]], - { "tag": "rowId", "path": [["GraphRealm"], ["root"], ["V"]] } - ], - [ - [["b"]], - { "tag": "rowId", "path": [["GraphRealm"], ["root"], ["V"]] } - ] - ], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphRealm"], ["root"], ["E"]], - "rowId": null, - "values": [ - { "tag": "var", "index": 0 }, - { "tag": "var", "index": 1 } - ] - } - } - ], - "consequents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphRealm"], ["root"], ["V"]], - "rowId": { "tag": "var", "index": 0 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphRealm"], ["root"], ["V"]], - "rowId": { "tag": "var", "index": 1 }, - "values": [] - } - } - ] - } - } - ] -} +{"entities":[{"path":[["GraphRealm"],["root"],["V"]],"value":{"entityVariant":{"tag":"table"},"columns":[],"primaryKey":null}},{"path":[["GraphRealm"],["root"],["E"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphRealm"],["root"],["V"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphRealm"],["root"],["V"]]}}],"primaryKey":null}}],"definitions":[],"rules":[{"path":[["GraphRealm"],["root"],["V"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphRealm"],["root"],["V"]],"rowId":null,"values":[]}}],"consequents":[]}},{"path":[["GraphRealm"],["root"],["E"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["GraphRealm"],["root"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphRealm"],["root"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphRealm"],["root"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphRealm"],["root"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphRealm"],["root"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}}]}}]} \ No newline at end of file diff --git a/packages/coln-js-runtime/src/rust/handles.rs b/packages/coln-js-runtime/src/rust/handles.rs index b4c3bdf2..b033f815 100644 --- a/packages/coln-js-runtime/src/rust/handles.rs +++ b/packages/coln-js-runtime/src/rust/handles.rs @@ -420,6 +420,7 @@ mod tests { primary_key: None, }, }], + definitions: vec![], rules: vec![], }; let mut store = Store::try_from_ir(theory).expect("store"); diff --git a/packages/coln-query/src/api/query.rs b/packages/coln-query/src/api/query.rs index 0d3c6716..d82eec4f 100644 --- a/packages/coln-query/src/api/query.rs +++ b/packages/coln-query/src/api/query.rs @@ -150,7 +150,7 @@ impl FlirProgram { fn table_declaration(&mut self, table_entry: &TableEntry) -> Result<(), SyntaxError> { match &table_entry.table.entity_variant { EntityVariant::Table => self.base_table(table_entry), - EntityVariant::View(materialization) => { + EntityVariant::View { materialization } => { unimplemented!("[Initial models] Materialized views defined through a query"); } EntityVariant::Index { method, columns } => { diff --git a/packages/coln-store/src/commit/graph.rs b/packages/coln-store/src/commit/graph.rs index 91d6f799..fa3fed3d 100644 --- a/packages/coln-store/src/commit/graph.rs +++ b/packages/coln-store/src/commit/graph.rs @@ -155,6 +155,7 @@ mod tests { primary_key: None, }, }], + definitions: vec![], rules: vec![], }) .expect("build root commit") diff --git a/packages/coln-store/src/commit/mod.rs b/packages/coln-store/src/commit/mod.rs index ff4fbe0f..39b68728 100644 --- a/packages/coln-store/src/commit/mod.rs +++ b/packages/coln-store/src/commit/mod.rs @@ -368,7 +368,7 @@ mod tests { builtin_ty: BuiltinTy::BuiltinInt, }, }], - primary_key: Some(vec![Path::from("c0")]), + primary_key: Some(vec![0]), } } @@ -378,6 +378,7 @@ mod tests { path: Path::from("T"), table: owned_int_schema(), }], + definitions: vec![], rules: vec![], } } @@ -579,10 +580,7 @@ mod tests { assert_eq!(decoded.tables.len(), 1); assert_eq!(decoded.tables[0].path, Path::from("T")); assert_eq!(decoded.tables[0].table.columns, owned_int_schema().columns); - assert_eq!( - decoded.tables[0].table.primary_key, - Some(vec![Path::from("c0")]) - ); + assert_eq!(decoded.tables[0].table.primary_key, Some(vec![0])); assert!(decoded.rules.is_empty()); } diff --git a/packages/coln-store/src/commit/pst.rs b/packages/coln-store/src/commit/pst.rs index 0b198cd1..fcf81532 100644 --- a/packages/coln-store/src/commit/pst.rs +++ b/packages/coln-store/src/commit/pst.rs @@ -121,6 +121,7 @@ mod tests { path: Path::from("T"), table: int_schema(), }], + definitions: vec![], rules: vec![], } } diff --git a/packages/coln-store/src/commit/wire/root.rs b/packages/coln-store/src/commit/wire/root.rs index dc50d5f6..a7c3effd 100644 --- a/packages/coln-store/src/commit/wire/root.rs +++ b/packages/coln-store/src/commit/wire/root.rs @@ -20,8 +20,8 @@ mod tests { use super::*; use crate::ir::{ - Atom, BuiltinTy, ColType, ColumnEntry, EntityVariant, Path, Prop, Rule, RuleEntry, - RuleVariant, Schema, TableEntry, El, ValueEntry, + Atom, BuiltinTy, ColType, ColumnEntry, El, EntityVariant, Path, Prop, Rule, RuleEntry, + RuleVariant, Schema, TableEntry, ValueEntry, }; fn int_schema() -> Schema { @@ -33,7 +33,7 @@ mod tests { builtin_ty: BuiltinTy::BuiltinInt, }, }], - primary_key: Some(vec![Path::from("c0")]), + primary_key: Some(vec![0]), } } @@ -63,10 +63,12 @@ mod tests { path: Path::from("T.non_negative"), rule: Rule { rule_variant: RuleVariant::Enforced, - var_names: vec![Path::from("x")], - var_types: vec![ColType::BuiltinTy { - builtin_ty: BuiltinTy::BuiltinInt, - }], + vars: vec![( + Path::from("x"), + ColType::BuiltinTy { + builtin_ty: BuiltinTy::BuiltinInt, + }, + )], antecedents: vec![Prop::Atom { atom: Atom { entity: table.clone(), @@ -91,6 +93,7 @@ mod tests { fn root_payload_round_trips() { let root = FlatRealm { tables: vec![table_entry("T", int_schema())], + definitions: vec![], rules: vec![simple_rule()], }; @@ -100,10 +103,7 @@ mod tests { assert_eq!(decoded.tables.len(), 1); assert_eq!(decoded.tables[0].path, Path::from("T")); assert_eq!(decoded.tables[0].table.columns, int_schema().columns); - assert_eq!( - decoded.tables[0].table.primary_key, - Some(vec![Path::from("c0")]) - ); + assert_eq!(decoded.tables[0].table.primary_key, Some(vec![0])); assert_eq!(decoded.rules.len(), 1); assert_eq!(decoded.rules[0].path, Path::from("T.non_negative")); } @@ -115,10 +115,12 @@ mod tests { let left = FlatRealm { tables: vec![b.clone(), a.clone()], + definitions: vec![], rules: vec![], }; let right = FlatRealm { tables: vec![a, b], + definitions: vec![], rules: vec![], }; @@ -132,6 +134,7 @@ mod tests { fn root_payload_rejects_trailing_bytes() { let root = FlatRealm { tables: vec![], + definitions: vec![], rules: vec![], }; diff --git a/packages/coln-store/src/repl/exe/mod.rs b/packages/coln-store/src/repl/exe/mod.rs index 3ba464d7..b7b64abb 100644 --- a/packages/coln-store/src/repl/exe/mod.rs +++ b/packages/coln-store/src/repl/exe/mod.rs @@ -219,7 +219,7 @@ pub struct TableSummary { pub enum PrimaryKeySummary { None, Singleton, - Columns(Vec), + Columns(Vec), } pub struct LoadedState { diff --git a/packages/coln-store/src/solver/bind.rs b/packages/coln-store/src/solver/bind.rs index 16fc3c0e..cfcf5c72 100644 --- a/packages/coln-store/src/solver/bind.rs +++ b/packages/coln-store/src/solver/bind.rs @@ -186,10 +186,11 @@ mod tests { path: Path::from(path), rule: Rule { rule_variant: RuleVariant::Enforced, - var_names: (0..var_types.len()) - .map(|index| Path::from(format!("v{index}"))) + vars: var_types + .into_iter() + .enumerate() + .map(|(i, ty)| (Path::from(format!("v{i}")), ty)) .collect(), - var_types, antecedents, consequents, }, diff --git a/packages/coln-store/src/solver/compile.rs b/packages/coln-store/src/solver/compile.rs index 81519ed5..fae1236d 100644 --- a/packages/coln-store/src/solver/compile.rs +++ b/packages/coln-store/src/solver/compile.rs @@ -4,7 +4,7 @@ use std::{collections::HashSet, fmt}; -use crate::ir::{self, Atom, Prop, RuleEntry, El}; +use crate::ir::{self, Atom, El, Prop, RuleEntry}; /// Errors raised while lowering an `ir::Rule` into the restricted solver form. #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] @@ -89,11 +89,11 @@ pub fn compile_rule(rule_entry: &RuleEntry) -> Result { let path = rule_entry.path.clone(); let vars = rule_entry .rule - .var_types + .vars .clone() .into_iter() .enumerate() - .map(|(index, ty)| VarSpec { index, ty }) + .map(|(index, (_, ty))| VarSpec { index, ty }) .collect::>(); let var_count = vars.len(); @@ -359,10 +359,11 @@ mod tests { path: Path::from(path), rule: Rule { rule_variant: RuleVariant::Enforced, - var_names: (0..var_types.len()) - .map(|index| Path::from(format!("v{index}"))) + vars: var_types + .into_iter() + .enumerate() + .map(|(i, ty)| (Path::from(format!("v{i}")), ty)) .collect(), - var_types, antecedents, consequents, }, diff --git a/packages/coln-store/src/solver/validate.rs b/packages/coln-store/src/solver/validate.rs index a730da18..01789111 100644 --- a/packages/coln-store/src/solver/validate.rs +++ b/packages/coln-store/src/solver/validate.rs @@ -191,10 +191,11 @@ mod tests { path: Path::from(path), rule: Rule { rule_variant: RuleVariant::Enforced, - var_names: (0..var_types.len()) - .map(|index| Path::from(format!("v{index}"))) + vars: var_types + .into_iter() + .enumerate() + .map(|(i, ty)| (Path::from(format!("v{i}")), ty)) .collect(), - var_types, antecedents, consequents, }, diff --git a/packages/coln-store/src/store/mod.rs b/packages/coln-store/src/store/mod.rs index f6ef104a..9c15cd06 100644 --- a/packages/coln-store/src/store/mod.rs +++ b/packages/coln-store/src/store/mod.rs @@ -104,6 +104,7 @@ impl Store { pub fn new() -> Self { let commits = Self::graph_with_root_commit(&FlatRealm { tables: Vec::new(), + definitions: Vec::new(), rules: Vec::new(), }) .expect("empty root commit should build"); @@ -741,6 +742,7 @@ impl Store { tables.sort_by_key(|(oid, _)| *oid); let ir = FlatRealm { tables: tables.into_iter().map(|(_, entry)| entry).collect(), + definitions: Vec::new(), rules: self.rule_entries.clone(), }; self.commits = Self::graph_with_root_commit(&ir)?; diff --git a/packages/coln-store/src/store/tests.rs b/packages/coln-store/src/store/tests.rs index 82032a64..9c1b86e7 100644 --- a/packages/coln-store/src/store/tests.rs +++ b/packages/coln-store/src/store/tests.rs @@ -48,6 +48,7 @@ pub(crate) mod test_support { table: int_entity(&["a", "b"]), }, ], + definitions: Vec::new(), rules: vec![RuleEntry { path: Path::from("Link.foreignKeys"), rule: Rule { @@ -262,7 +263,7 @@ mod transactions { builtin_ty: BuiltinTy::BuiltinInt, }, }], - primary_key: Some(vec![Path::from("c0")]), + primary_key: Some(vec![0u64]), }; let mut store = Store::new(); store @@ -479,7 +480,7 @@ mod rowing { Schema { entity_variant: EntityVariant::Table, columns: vec![id_col("x", "Term"), id_col("y", "Term")], - primary_key: Some(vec![Path::from("x")]), + primary_key: Some(vec![0u64]), }, ), ] { diff --git a/packages/coln-store/src/table/mod.rs b/packages/coln-store/src/table/mod.rs index 4a6100ce..b5c282f5 100644 --- a/packages/coln-store/src/table/mod.rs +++ b/packages/coln-store/src/table/mod.rs @@ -123,7 +123,6 @@ pub struct Table { oid: TableOid, path: ir::Path, schema: Schema, - col_name_map: HashMap, /// Structural (all-columns) index used for structural identification, when enabled. structural_index: Option, indexes: Vec, @@ -141,12 +140,6 @@ impl Table { // Basic accessors pub fn new(path: ir::Path, oid: TableOid, schema: Schema) -> Self { - let col_name_map: HashMap = schema - .columns - .iter() - .enumerate() - .map(|(i, column)| (column.path.clone(), i)) - .collect(); let cols = schema .columns .iter() @@ -163,12 +156,7 @@ impl Table { let key_cols: Vec = pk .iter() // we can expect the schema to contain right information - .map(|name| { - col_name_map - .get(name) - .copied() - .expect("schema pk spec is correct") - }) + .map(|n| *n as usize) .collect(); indexes.push(TableIndex::new(&key_cols, &schema)); // ? Is referring to the index id the right thing to do? @@ -185,7 +173,6 @@ impl Table { Self { oid, path, - col_name_map, schema, structural_index, row_ids: IdColumn::new(), @@ -459,12 +446,7 @@ impl Table { if pk.is_empty() { Some(Vec::new()) } else { - pk.iter() - .map(|name| { - let i = self.col_name_map.get(name).copied()?; - Some(values[i].clone()) - }) - .collect() + pk.iter().map(|i| Some(values[*i as usize].clone())).collect() } }) } diff --git a/packages/coln-store/src/table/sorted.rs b/packages/coln-store/src/table/sorted.rs index ce6fe0e2..e77cf1b4 100644 --- a/packages/coln-store/src/table/sorted.rs +++ b/packages/coln-store/src/table/sorted.rs @@ -183,7 +183,7 @@ mod tests { }, }, ], - primary_key: Some(vec![Path::from("c0")]), + primary_key: Some(vec![0]), }; let mut store = Store::new(); let oid = store.create_table(path, schema).expect("create test table"); diff --git a/packages/coln-store/src/table/tests.rs b/packages/coln-store/src/table/tests.rs index 1ec7c5fc..e7180c3d 100644 --- a/packages/coln-store/src/table/tests.rs +++ b/packages/coln-store/src/table/tests.rs @@ -173,7 +173,7 @@ fn row_count_matches_inserts_when_schema_has_no_columns() { #[test] fn rollback_removes_applied_rows_and_index_entries() { let path = Path::from("rollback"); - let mut tbl = TestTable::new(path.clone(), int_schema(&["value"], Some(&["value"]))); + let mut tbl = TestTable::new(path.clone(), int_schema(&["value"], Some(&[0]))); let existing = test_row_id(0); let first_added = test_row_id(1); let second_added = test_row_id(2); @@ -215,10 +215,7 @@ fn rollback_removes_applied_rows_and_index_entries() { /// stages to move a row, so both directions have to keep indexes in step. #[test] fn staged_delete_removes_row_and_undo_restores_it() { - let mut tbl = TestTable::new( - Path::from("deleting"), - int_schema(&["value"], Some(&["value"])), - ); + let mut tbl = TestTable::new(Path::from("deleting"), int_schema(&["value"], Some(&[0]))); let kept = test_row_id(0); let removed = test_row_id(1); tbl.insert_row(vec![WireValue::Int(1)], kept); @@ -544,7 +541,7 @@ fn rows_stay_sorted_by_row_id() { #[test] fn primary_key_detects_duplicates_in_id_columns() { let mut schema = id_schema(&["src", "dst"]); - schema.primary_key = Some(vec![Path::from("src")]); + schema.primary_key = Some(vec![0]); let mut tbl = TestTable::new(Path::from("edges"), schema); let src = row_id_from(3, 7); @@ -566,7 +563,7 @@ fn primary_key_detects_duplicates_in_id_columns() { assert!(tbl.validate_insert(&unseen_commit).is_ok()); } -fn int_schema(columns: &[&str], primary_key: Option<&[&str]>) -> ir::Schema { +fn int_schema(columns: &[&str], primary_key: Option<&[u64]>) -> ir::Schema { ir::Schema { entity_variant: ir::EntityVariant::Table, columns: columns @@ -578,7 +575,7 @@ fn int_schema(columns: &[&str], primary_key: Option<&[&str]>) -> ir::Schema { }, }) .collect(), - primary_key: primary_key.map(|pk| pk.iter().map(|name| Path::from(*name)).collect()), + primary_key: primary_key.map(|pk| pk.into()), } } @@ -586,7 +583,7 @@ fn int_schema(columns: &[&str], primary_key: Option<&[&str]>) -> ir::Schema { /// sharing only one key column, regardless of insert order. #[test] fn multi_column_primary_key_checks_all_columns() { - let schema = int_schema(&["c0", "c1", "c2"], Some(&["c0", "c1"])); + let schema = int_schema(&["c0", "c1", "c2"], Some(&[0, 1])); let mut tbl = TestTable::new(Path::from("pairs"), schema); let rows = [(3, 1), (1, 2), (1, 1), (2, 1), (2, 2)]; @@ -618,7 +615,7 @@ fn string_primary_key_detects_duplicates() { builtin_ty: BuiltinTy::BuiltinStr, }, }], - primary_key: Some(vec![Path::from("name")]), + primary_key: Some(vec![0]), }; let mut tbl = TestTable::new(Path::from("named"), schema); @@ -641,11 +638,6 @@ fn string_primary_key_detects_duplicates() { /// Schemas are compiler-generated, so a primary key referencing an /// unknown column is a bug and fails table construction. #[test] -#[should_panic(expected = "schema pk spec is correct")] -fn invalid_primary_key_name_panics_at_construction() { - let schema = int_schema(&["c0"], Some(&["missing"])); - Table::new(Path::from("broken"), 0, schema); -} /// Manual benchmark for the primary key duplicate check on insert. /// Inserting `n` rows of one integer (the primary key) and one row id. @@ -670,7 +662,7 @@ fn pk_insert_benchmark() { }, }, ], - primary_key: Some(vec![Path::from("c0")]), + primary_key: Some(vec![0]), }; let mut tbl = TestTable::new(Path::from("bench"), schema); let n = 50_000; @@ -688,7 +680,7 @@ fn pk_insert_benchmark() { /// a non-indexed lookup and both should work. #[test] fn table_performs_index_lookup() { - let schema = int_schema(&["indexed", "plain"], Some(&["indexed"])); + let schema = int_schema(&["indexed", "plain"], Some(&[0])); let mut tbl = TestTable::new(Path::from("lookup"), schema); tbl.insert_row(vec![WireValue::Int(7), WireValue::Int(70)], test_row_id(0)); tbl.insert_row(vec![WireValue::Int(8), WireValue::Int(80)], test_row_id(1)); @@ -730,7 +722,7 @@ fn table_performs_index_lookup() { /// which is then rejected by the table. #[test] fn table_index_lookup_non_existing_index() { - let schema = int_schema(&["indexed"], Some(&["indexed"])); + let schema = int_schema(&["indexed"], Some(&[00])); let tbl = TestTable::new(Path::from("lookup"), schema); assert_eq!( @@ -743,7 +735,7 @@ fn table_index_lookup_non_existing_index() { /// index shape, which should be rejected as an error. #[test] fn table_index_lookup_incorrect_key() { - let schema = int_schema(&["indexed", "plain"], Some(&["indexed"])); + let schema = int_schema(&["indexed", "plain"], Some(&[0])); let tbl = TestTable::new(Path::from("lookup"), schema); let index = tbl.table.primary_index().expect("primary-key index"); @@ -764,7 +756,7 @@ fn table_index_lookup_incorrect_key() { /// negative) #[test] fn table_index_non_index_give_same_results() { - let schema = int_schema(&["indexed", "plain"], Some(&["indexed"])); + let schema = int_schema(&["indexed", "plain"], Some(&[0])); let mut tbl = TestTable::new(Path::from("lookup"), schema); for value in [7, 8] { let row_id = test_row_id(tbl.row_count() as u32); diff --git a/packages/coln-store/src/txn/mod.rs b/packages/coln-store/src/txn/mod.rs index 15ce5f80..666f0e6d 100644 --- a/packages/coln-store/src/txn/mod.rs +++ b/packages/coln-store/src/txn/mod.rs @@ -104,7 +104,7 @@ mod tests { use crate::table::{ValidationError, WireValue}; use crate::txn::row_handle::empty_row; - fn table_schema(columns: Vec, primary_key: Option>) -> Schema { + fn table_schema(columns: Vec, primary_key: Option>) -> Schema { Schema { entity_variant: EntityVariant::Table, columns, diff --git a/packages/coln-store/tests/test_path.rs b/packages/coln-store/tests/test_path.rs index 07b92584..fb945350 100644 --- a/packages/coln-store/tests/test_path.rs +++ b/packages/coln-store/tests/test_path.rs @@ -134,7 +134,7 @@ fn test_read_path_coln() { .find(|e| e.path == Path::from("Path.Hom.E.foreignKey")) .expect("Path.Hom.E.foreignKey law path"); assert!( - !hom_e_fk.rule.var_names.is_empty(), + !hom_e_fk.rule.vars.is_empty(), "Hom,E foreignKeys law should bind variables" ); } diff --git a/packages/coln-store/tests/test_subduction.rs b/packages/coln-store/tests/test_subduction.rs index a2cbe442..e6a5c5a8 100644 --- a/packages/coln-store/tests/test_subduction.rs +++ b/packages/coln-store/tests/test_subduction.rs @@ -49,6 +49,7 @@ fn int_theory() -> FlatRealm { primary_key: None, }, }], + definitions: vec![], rules: vec![], } } From e929d92c3f1dbcf90824e9e75918789fc8ee3f15 Mon Sep 17 00:00:00 2001 From: Leo Stewen Date: Thu, 10 Sep 2026 07:34:14 +0200 Subject: [PATCH 37/42] [coln-flir-rs] Pretty print the FLIR JSON files --- .../tests/data/GraphOfGraphsRealm.json | 900 +++++++++++++++++- .../coln-flir-rs/tests/data/GraphRealm.json | 104 +- 2 files changed, 1002 insertions(+), 2 deletions(-) diff --git a/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json b/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json index bc511314..d0016f84 100644 --- a/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json +++ b/packages/coln-flir-rs/tests/data/GraphOfGraphsRealm.json @@ -1 +1,899 @@ -{"entities":[{"path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"value":{"entityVariant":{"tag":"table"},"columns":[],"primaryKey":null}},{"path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}}],"primaryKey":null}},{"path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}}],"primaryKey":null}},{"path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}},{"path":[["c"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}}],"primaryKey":null}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["v0"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["v1"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}},{"path":[["V"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}}],"primaryKey":[0,1,2,3]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["E"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["v0"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["v1"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}},{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}},{"path":[["v0","a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}},{"path":[["v1","a"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}},{"path":[["E"]],"type":{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}}],"primaryKey":[0,1,2,3,4,5]}}],"definitions":[],"rules":[{"path":[["GraphOfGraphsRealm"],["root"],["base"],["V"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":null,"values":[]}}],"consequents":[]}},{"path":[["GraphOfGraphsRealm"],["root"],["base"],["E"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["c"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":1},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}}]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["V"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["v0"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["v1"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["V"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}},{"column":4,"term":{"tag":"var","index":4}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":3},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":4},"values":[{"column":0,"term":{"tag":"var","index":1}}]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["V"],["total"]],"value":{"ruleVariant":"monitored","vars":[[[["v0"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["v1"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":3},"values":[{"column":0,"term":{"tag":"var","index":0}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}}]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["E"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["v0"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["v1"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}],[[["v0","a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["v1","a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}],[[["E"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}],[[["c"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["d"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}},{"column":4,"term":{"tag":"var","index":4}},{"column":5,"term":{"tag":"var","index":5}},{"column":6,"term":{"tag":"var","index":6}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":3},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":4},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"rowId":{"tag":"var","index":5},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":3}},{"column":2,"term":{"tag":"var","index":4}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}},{"column":4,"term":{"tag":"var","index":7}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["V"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":4}},{"column":4,"term":{"tag":"var","index":8}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"rowId":{"tag":"var","index":6},"values":[{"column":0,"term":{"tag":"var","index":1}},{"column":1,"term":{"tag":"var","index":7}},{"column":2,"term":{"tag":"var","index":8}}]}}]}},{"path":[["GraphOfGraphsRealm"],["root"],["action"],["E"],["total"]],"value":{"ruleVariant":"monitored","vars":[[[["v0"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["v1"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["V"]]}],[[["a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["base"],["E"]]}],[[["v0","a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["v1","a"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["base"],["E"]],"rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":3},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["V"]],"rowId":{"tag":"var","index":4},"values":[{"column":0,"term":{"tag":"var","index":0}}]}},{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["fiber"],["E"]],"rowId":{"tag":"var","index":5},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":3}},{"column":2,"term":{"tag":"var","index":4}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphOfGraphsRealm"],["root"],["action"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}},{"column":2,"term":{"tag":"var","index":2}},{"column":3,"term":{"tag":"var","index":3}},{"column":4,"term":{"tag":"var","index":4}},{"column":5,"term":{"tag":"var","index":5}}]}}]}}]} \ No newline at end of file +{ + "entities": [ + { + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [], + "primaryKey": null + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + } + ], + "primaryKey": null + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + } + ], + "primaryKey": null + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + }, + { + "path": [["c"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + } + ], + "primaryKey": null + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["v0"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["v1"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + }, + { + "path": [["V"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + } + ], + "primaryKey": [0, 1, 2, 3] + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["v0"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["v1"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + }, + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + }, + { + "path": [["v0", "a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + }, + { + "path": [["v1", "a"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + }, + { + "path": [["E"]], + "type": { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + } + ], + "primaryKey": [0, 1, 2, 3, 4, 5] + } + } + ], + "definitions": [], + "rules": [ + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["base"], + ["V"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": null, + "values": [] + } + } + ], + "consequents": [] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["base"], + ["E"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + } + ] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["fiber"], + ["V"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": null, + "values": [{ "column": 0, "term": { "tag": "var", "index": 0 } }] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + } + ] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["fiber"], + ["E"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["c"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } }, + { "column": 2, "term": { "tag": "var", "index": 2 } } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [{ "column": 0, "term": { "tag": "var", "index": 0 } }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [{ "column": 0, "term": { "tag": "var", "index": 0 } }] + } + } + ] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["action"], + ["V"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["v0"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["v1"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["V"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } }, + { "column": 2, "term": { "tag": "var", "index": 2 } }, + { "column": 3, "term": { "tag": "var", "index": 3 } }, + { "column": 4, "term": { "tag": "var", "index": 4 } } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [{ "column": 0, "term": { "tag": "var", "index": 0 } }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 4 }, + "values": [{ "column": 0, "term": { "tag": "var", "index": 1 } }] + } + } + ] + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"], ["total"]], + "value": { + "ruleVariant": "monitored", + "vars": [ + [ + [["v0"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["v1"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [{ "column": 0, "term": { "tag": "var", "index": 0 } }] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } }, + { "column": 2, "term": { "tag": "var", "index": 2 } }, + { "column": 3, "term": { "tag": "var", "index": 3 } } + ] + } + } + ] + } + }, + { + "path": [ + ["GraphOfGraphsRealm"], + ["root"], + ["action"], + ["E"], + ["foreignKey"] + ], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["v0"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["v1"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + ], + [ + [["v0", "a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["v1", "a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + ], + [ + [["E"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + ], + [ + [["c"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["d"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } }, + { "column": 2, "term": { "tag": "var", "index": 2 } }, + { "column": 3, "term": { "tag": "var", "index": 3 } }, + { "column": 4, "term": { "tag": "var", "index": 4 } }, + { "column": 5, "term": { "tag": "var", "index": 5 } }, + { "column": 6, "term": { "tag": "var", "index": 6 } } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [{ "column": 0, "term": { "tag": "var", "index": 0 } }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 4 }, + "values": [{ "column": 0, "term": { "tag": "var", "index": 0 } }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "rowId": { "tag": "var", "index": 5 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 3 } }, + { "column": 2, "term": { "tag": "var", "index": 4 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } }, + { "column": 2, "term": { "tag": "var", "index": 2 } }, + { "column": 3, "term": { "tag": "var", "index": 3 } }, + { "column": 4, "term": { "tag": "var", "index": 7 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["V"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } }, + { "column": 2, "term": { "tag": "var", "index": 2 } }, + { "column": 3, "term": { "tag": "var", "index": 4 } }, + { "column": 4, "term": { "tag": "var", "index": 8 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "rowId": { "tag": "var", "index": 6 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 1 } }, + { "column": 1, "term": { "tag": "var", "index": 7 } }, + { "column": 2, "term": { "tag": "var", "index": 8 } } + ] + } + } + ] + } + }, + { + "path": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"], ["total"]], + "value": { + "ruleVariant": "monitored", + "vars": [ + [ + [["v0"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["v1"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]] + } + ], + [ + [["a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]] + } + ], + [ + [["v0", "a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["v1", "a"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["base"], ["E"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [{ "column": 0, "term": { "tag": "var", "index": 0 } }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["V"]], + "rowId": { "tag": "var", "index": 4 }, + "values": [{ "column": 0, "term": { "tag": "var", "index": 0 } }] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["fiber"], ["E"]], + "rowId": { "tag": "var", "index": 5 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 3 } }, + { "column": 2, "term": { "tag": "var", "index": 4 } } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphOfGraphsRealm"], ["root"], ["action"], ["E"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } }, + { "column": 2, "term": { "tag": "var", "index": 2 } }, + { "column": 3, "term": { "tag": "var", "index": 3 } }, + { "column": 4, "term": { "tag": "var", "index": 4 } }, + { "column": 5, "term": { "tag": "var", "index": 5 } } + ] + } + } + ] + } + } + ] +} diff --git a/packages/coln-flir-rs/tests/data/GraphRealm.json b/packages/coln-flir-rs/tests/data/GraphRealm.json index b717644c..492596b7 100644 --- a/packages/coln-flir-rs/tests/data/GraphRealm.json +++ b/packages/coln-flir-rs/tests/data/GraphRealm.json @@ -1 +1,103 @@ -{"entities":[{"path":[["GraphRealm"],["root"],["V"]],"value":{"entityVariant":{"tag":"table"},"columns":[],"primaryKey":null}},{"path":[["GraphRealm"],["root"],["E"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["GraphRealm"],["root"],["V"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["GraphRealm"],["root"],["V"]]}}],"primaryKey":null}}],"definitions":[],"rules":[{"path":[["GraphRealm"],["root"],["V"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphRealm"],["root"],["V"]],"rowId":null,"values":[]}}],"consequents":[]}},{"path":[["GraphRealm"],["root"],["E"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["GraphRealm"],["root"],["V"]]}],[[["b"]],{"tag":"rowId","path":[["GraphRealm"],["root"],["V"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["GraphRealm"],["root"],["E"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["GraphRealm"],["root"],["V"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["GraphRealm"],["root"],["V"]],"rowId":{"tag":"var","index":1},"values":[]}}]}}]} \ No newline at end of file +{ + "entities": [ + { + "path": [["GraphRealm"], ["root"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [], + "primaryKey": null + } + }, + { + "path": [["GraphRealm"], ["root"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["GraphRealm"], ["root"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["GraphRealm"], ["root"], ["V"]] + } + } + ], + "primaryKey": null + } + } + ], + "definitions": [], + "rules": [ + { + "path": [["GraphRealm"], ["root"], ["V"], ["foreignKey"]], + "value": { + "ruleVariant": "enforced", + "vars": [], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphRealm"], ["root"], ["V"]], + "rowId": null, + "values": [] + } + } + ], + "consequents": [] + } + }, + { + "path": [["GraphRealm"], ["root"], ["E"], ["foreignKey"]], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { "tag": "rowId", "path": [["GraphRealm"], ["root"], ["V"]] } + ], + [ + [["b"]], + { "tag": "rowId", "path": [["GraphRealm"], ["root"], ["V"]] } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphRealm"], ["root"], ["E"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["GraphRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["GraphRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + } + ] + } + } + ] +} From be9ddd16c0f051be2e35538686cbab6b92b00563 Mon Sep 17 00:00:00 2001 From: Leo Stewen Date: Thu, 10 Sep 2026 07:39:06 +0200 Subject: [PATCH 38/42] [coln-flir-rs] Fix the goddamn test to align with the updated FLIR --- packages/coln-flir-rs/tests/test_theory.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/coln-flir-rs/tests/test_theory.rs b/packages/coln-flir-rs/tests/test_theory.rs index 5838cf80..3e3f7f4f 100644 --- a/packages/coln-flir-rs/tests/test_theory.rs +++ b/packages/coln-flir-rs/tests/test_theory.rs @@ -22,10 +22,13 @@ fn deserialises_graph_theory() { assert_eq!(theory.tables.len(), 2); assert_eq!(theory.rules.len(), 2); - assert_eq!(theory.tables[0].path, Path::from("Graph.E")); - assert_eq!(theory.tables[1].path, Path::from("Graph.V")); + assert_eq!(theory.tables[0].path, Path::from("GraphRealm.root.V")); + assert_eq!(theory.tables[1].path, Path::from("GraphRealm.root.E")); - let rules = &theory.rules[0]; - assert_eq!(rules.path, Path::from("Graph.E.foreignKey")); - assert_eq!(rules.rule.vars.len(), 2); + let e_foreign_key_rule = &theory.rules[1]; + assert_eq!( + e_foreign_key_rule.path, + Path::from("GraphRealm.root.E.foreignKey") + ); + assert_eq!(e_foreign_key_rule.rule.vars.len(), 2); } From 45e62e5ac66588c43e61f756cfd1281b1a507241 Mon Sep 17 00:00:00 2001 From: Leo Stewen Date: Thu, 10 Sep 2026 07:48:23 +0200 Subject: [PATCH 39/42] [coln-flir-rs] Provide two more JSON FLIRs as requested: One with a derived view defined by a conjunctive query (TriangleRealm.json) and another one with a derived view defined with self-recursion (TransitiveClosureRealm.json) --- .../test/golden/transitive-closure.coln | 2 +- .../coln-compiler/test/golden/triangle.coln | 2 +- .../tests/data/TransitiveClosureRealm.json | 280 ++++++++++++++++++ .../tests/data/TransitiveClosureRealm.pretty | 30 ++ .../tests/data/TriangleRealm.json | 254 ++++++++++++++++ .../tests/data/TriangleRealm.pretty | 47 +++ packages/coln-flir-rs/tests/test_theory.rs | 7 +- 7 files changed, 619 insertions(+), 3 deletions(-) create mode 100644 packages/coln-flir-rs/tests/data/TransitiveClosureRealm.json create mode 100644 packages/coln-flir-rs/tests/data/TransitiveClosureRealm.pretty create mode 100644 packages/coln-flir-rs/tests/data/TriangleRealm.json create mode 100644 packages/coln-flir-rs/tests/data/TriangleRealm.pretty diff --git a/packages/coln-compiler/test/golden/transitive-closure.coln b/packages/coln-compiler/test/golden/transitive-closure.coln index 8cbe2b7c..7ca27d90 100644 --- a/packages/coln-compiler/test/golden/transitive-closure.coln +++ b/packages/coln-compiler/test/golden/transitive-closure.coln @@ -9,6 +9,6 @@ theory TransExt (^i G : Graph) := sig snoc : (v0 : G.V) -> (v1 : G.V) -> (v2 : G.V) -> connected v0 v1 -> G.E v1 v2 -> connected v0 v2 end -realm GraphRealm @ Graph +realm TransitiveClosureRealm @ Graph ind def trans-closure : TransExt root := init (TransExt root) end diff --git a/packages/coln-compiler/test/golden/triangle.coln b/packages/coln-compiler/test/golden/triangle.coln index 510534cb..ad021aba 100644 --- a/packages/coln-compiler/test/golden/triangle.coln +++ b/packages/coln-compiler/test/golden/triangle.coln @@ -3,7 +3,7 @@ theory Graph := sig E : V -> V -> Set end -realm GraphRealm @ Graph +realm TriangleRealm @ Graph def triangle : Set := sig a : root.V b : root.V diff --git a/packages/coln-flir-rs/tests/data/TransitiveClosureRealm.json b/packages/coln-flir-rs/tests/data/TransitiveClosureRealm.json new file mode 100644 index 00000000..82142168 --- /dev/null +++ b/packages/coln-flir-rs/tests/data/TransitiveClosureRealm.json @@ -0,0 +1,280 @@ +{ + "entities": [ + { + "path": [["TransitiveClosureRealm"], ["root"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [], + "primaryKey": null + } + }, + { + "path": [["TransitiveClosureRealm"], ["root"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + } + ], + "primaryKey": null + } + }, + { + "path": [ + ["TransitiveClosureRealm"], + ["init"], + ["trans-closure"], + ["connected"] + ], + "value": { + "entityVariant": { "tag": "view", "materialization": "memoized" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + } + ], + "primaryKey": [0, 1] + } + } + ], + "definitions": [ + { + "path": [ + ["TransitiveClosureRealm"], + ["init"], + ["trans-closure"], + ["refl"] + ], + "value": { + "vars": [ + [ + [["v"]], + { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["TransitiveClosureRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + } + ], + "definand": [ + ["TransitiveClosureRealm"], + ["init"], + ["trans-closure"], + ["connected"] + ], + "arguments": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 0 } + ] + } + }, + { + "path": [ + ["TransitiveClosureRealm"], + ["init"], + ["trans-closure"], + ["snoc"] + ], + "value": { + "vars": [ + [ + [["v0"]], + { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + ], + [ + [["v1"]], + { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + ], + [ + [["v2"]], + { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["E"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["TransitiveClosureRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TransitiveClosureRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TransitiveClosureRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [ + ["TransitiveClosureRealm"], + ["init"], + ["trans-closure"], + ["connected"] + ], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TransitiveClosureRealm"], ["root"], ["E"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 1 } }, + { "column": 1, "term": { "tag": "var", "index": 2 } } + ] + } + } + ], + "definand": [ + ["TransitiveClosureRealm"], + ["init"], + ["trans-closure"], + ["connected"] + ], + "arguments": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 2 } + ] + } + } + ], + "rules": [ + { + "path": [["TransitiveClosureRealm"], ["root"], ["V"], ["foreignKey"]], + "value": { + "ruleVariant": "enforced", + "vars": [], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["TransitiveClosureRealm"], ["root"], ["V"]], + "rowId": null, + "values": [] + } + } + ], + "consequents": [] + } + }, + { + "path": [["TransitiveClosureRealm"], ["root"], ["E"], ["foreignKey"]], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + ], + [ + [["b"]], + { + "tag": "rowId", + "path": [["TransitiveClosureRealm"], ["root"], ["V"]] + } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["TransitiveClosureRealm"], ["root"], ["E"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["TransitiveClosureRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TransitiveClosureRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + } + ] + } + } + ] +} diff --git a/packages/coln-flir-rs/tests/data/TransitiveClosureRealm.pretty b/packages/coln-flir-rs/tests/data/TransitiveClosureRealm.pretty new file mode 100644 index 00000000..1edc8cb1 --- /dev/null +++ b/packages/coln-flir-rs/tests/data/TransitiveClosureRealm.pretty @@ -0,0 +1,30 @@ +flatrealm + entities + table ℜ.root.V := [] + table ℜ.root.E := [.a : ℜ.root.V, .b : ℜ.root.V] + view ℜ.init.trans-closure.connected := [ + .a : ℜ.root.V, + .b : ℜ.root.V + ] primarykey [.a, .b] + end + definitions + chased ℜ.init.trans-closure.refl v := v ∈ ℜ.root.V [] ⊢ ℜ.init.trans-closure.connected [ + .a ↦ v, + .b ↦ v + ] + chased ℜ.init.trans-closure.snoc v0 v1 v2 b := v0 ∈ ℜ.root.V [] ∧ v1 ∈ ℜ.root.V [] ∧ v2 ∈ ℜ.root.V [] ∧ ℜ.init.trans-closure.connected [ + .a ↦ v0, + .b ↦ v1 + ] ∧ b ∈ ℜ.root.E [.a ↦ v1, .b ↦ v2] ⊢ ℜ.init.trans-closure.connected [ + .a ↦ v0, + .b ↦ v2 + ] + end + rules + enforced ℜ.root.V.foreignKey := ℜ.root.V [] ⊢ ⊤ + enforced ℜ.root.E.foreignKey a b := ℜ.root.E [ + .a ↦ a, + .b ↦ b + ] ⊢ a ∈ ℜ.root.V [] ∧ b ∈ ℜ.root.V [] + end +end \ No newline at end of file diff --git a/packages/coln-flir-rs/tests/data/TriangleRealm.json b/packages/coln-flir-rs/tests/data/TriangleRealm.json new file mode 100644 index 00000000..c7d75be8 --- /dev/null +++ b/packages/coln-flir-rs/tests/data/TriangleRealm.json @@ -0,0 +1,254 @@ +{ + "entities": [ + { + "path": [["TriangleRealm"], ["root"], ["V"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [], + "primaryKey": null + } + }, + { + "path": [["TriangleRealm"], ["root"], ["E"]], + "value": { + "entityVariant": { "tag": "table" }, + "columns": [ + { + "path": [["a"]], + "type": { + "tag": "rowId", + "path": [["TriangleRealm"], ["root"], ["V"]] + } + }, + { + "path": [["b"]], + "type": { + "tag": "rowId", + "path": [["TriangleRealm"], ["root"], ["V"]] + } + } + ], + "primaryKey": null + } + }, + { + "path": [["TriangleRealm"], ["view"], ["triangle"]], + "value": { + "entityVariant": { "tag": "view", "materialization": "materialized" }, + "columns": [ + { + "path": [["triangle"], ["a"]], + "type": { + "tag": "rowId", + "path": [["TriangleRealm"], ["root"], ["V"]] + } + }, + { + "path": [["triangle"], ["b"]], + "type": { + "tag": "rowId", + "path": [["TriangleRealm"], ["root"], ["V"]] + } + }, + { + "path": [["triangle"], ["c"]], + "type": { + "tag": "rowId", + "path": [["TriangleRealm"], ["root"], ["V"]] + } + }, + { + "path": [["triangle"], ["f"]], + "type": { + "tag": "rowId", + "path": [["TriangleRealm"], ["root"], ["E"]] + } + }, + { + "path": [["triangle"], ["g"]], + "type": { + "tag": "rowId", + "path": [["TriangleRealm"], ["root"], ["E"]] + } + }, + { + "path": [["triangle"], ["h"]], + "type": { + "tag": "rowId", + "path": [["TriangleRealm"], ["root"], ["E"]] + } + } + ], + "primaryKey": [0, 1, 2, 3, 4, 5] + } + } + ], + "definitions": [ + { + "path": [["TriangleRealm"], ["view"], ["triangle"], ["definition"]], + "value": { + "vars": [ + [ + [["triangle"], ["a"]], + { "tag": "rowId", "path": [["TriangleRealm"], ["root"], ["V"]] } + ], + [ + [["triangle"], ["b"]], + { "tag": "rowId", "path": [["TriangleRealm"], ["root"], ["V"]] } + ], + [ + [["triangle"], ["c"]], + { "tag": "rowId", "path": [["TriangleRealm"], ["root"], ["V"]] } + ], + [ + [["triangle"], ["f"]], + { "tag": "rowId", "path": [["TriangleRealm"], ["root"], ["E"]] } + ], + [ + [["triangle"], ["g"]], + { "tag": "rowId", "path": [["TriangleRealm"], ["root"], ["E"]] } + ], + [ + [["triangle"], ["h"]], + { "tag": "rowId", "path": [["TriangleRealm"], ["root"], ["E"]] } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 2 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["E"]], + "rowId": { "tag": "var", "index": 3 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["E"]], + "rowId": { "tag": "var", "index": 4 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 1 } }, + { "column": 1, "term": { "tag": "var", "index": 2 } } + ] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["E"]], + "rowId": { "tag": "var", "index": 5 }, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 2 } } + ] + } + } + ], + "definand": [["TriangleRealm"], ["view"], ["triangle"]], + "arguments": [ + { "tag": "var", "index": 0 }, + { "tag": "var", "index": 1 }, + { "tag": "var", "index": 2 }, + { "tag": "var", "index": 3 }, + { "tag": "var", "index": 4 }, + { "tag": "var", "index": 5 } + ] + } + } + ], + "rules": [ + { + "path": [["TriangleRealm"], ["root"], ["V"], ["foreignKey"]], + "value": { + "ruleVariant": "enforced", + "vars": [], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["V"]], + "rowId": null, + "values": [] + } + } + ], + "consequents": [] + } + }, + { + "path": [["TriangleRealm"], ["root"], ["E"], ["foreignKey"]], + "value": { + "ruleVariant": "enforced", + "vars": [ + [ + [["a"]], + { "tag": "rowId", "path": [["TriangleRealm"], ["root"], ["V"]] } + ], + [ + [["b"]], + { "tag": "rowId", "path": [["TriangleRealm"], ["root"], ["V"]] } + ] + ], + "antecedents": [ + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["E"]], + "rowId": null, + "values": [ + { "column": 0, "term": { "tag": "var", "index": 0 } }, + { "column": 1, "term": { "tag": "var", "index": 1 } } + ] + } + } + ], + "consequents": [ + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 0 }, + "values": [] + } + }, + { + "tag": "atom", + "atom": { + "entity": [["TriangleRealm"], ["root"], ["V"]], + "rowId": { "tag": "var", "index": 1 }, + "values": [] + } + } + ] + } + } + ] +} diff --git a/packages/coln-flir-rs/tests/data/TriangleRealm.pretty b/packages/coln-flir-rs/tests/data/TriangleRealm.pretty new file mode 100644 index 00000000..c8997903 --- /dev/null +++ b/packages/coln-flir-rs/tests/data/TriangleRealm.pretty @@ -0,0 +1,47 @@ +flatrealm + entities + table ℜ.root.V := [] + table ℜ.root.E := [.a : ℜ.root.V, .b : ℜ.root.V] + view ℜ.`view`.triangle := [ + .triangle.a : ℜ.root.V, + .triangle.b : ℜ.root.V, + .triangle.c : ℜ.root.V, + .triangle.f : ℜ.root.E, + .triangle.g : ℜ.root.E, + .triangle.h : ℜ.root.E + ] primarykey [ + .triangle.a, + .triangle.b, + .triangle.c, + .triangle.f, + .triangle.g, + .triangle.h + ] + end + definitions + chased ℜ.`view`.triangle.definition triangle.a triangle.b triangle.c triangle.f triangle.g triangle.h := triangle.a ∈ ℜ.root.V [] ∧ triangle.b ∈ ℜ.root.V [] ∧ triangle.c ∈ ℜ.root.V [] ∧ triangle.f ∈ ℜ.root.E [ + .a ↦ triangle.a, + .b ↦ triangle.b + ] ∧ triangle.g ∈ ℜ.root.E [ + .a ↦ triangle.b, + .b ↦ triangle.c + ] ∧ triangle.h ∈ ℜ.root.E [ + .a ↦ triangle.a, + .b ↦ triangle.c + ] ⊢ ℜ.`view`.triangle [ + .triangle.a ↦ triangle.a, + .triangle.b ↦ triangle.b, + .triangle.c ↦ triangle.c, + .triangle.f ↦ triangle.f, + .triangle.g ↦ triangle.g, + .triangle.h ↦ triangle.h + ] + end + rules + enforced ℜ.root.V.foreignKey := ℜ.root.V [] ⊢ ⊤ + enforced ℜ.root.E.foreignKey a b := ℜ.root.E [ + .a ↦ a, + .b ↦ b + ] ⊢ a ∈ ℜ.root.V [] ∧ b ∈ ℜ.root.V [] + end +end \ No newline at end of file diff --git a/packages/coln-flir-rs/tests/test_theory.rs b/packages/coln-flir-rs/tests/test_theory.rs index 3e3f7f4f..f1471c6b 100644 --- a/packages/coln-flir-rs/tests/test_theory.rs +++ b/packages/coln-flir-rs/tests/test_theory.rs @@ -6,7 +6,12 @@ use coln_flir_rs::ir::Path; use coln_flir_rs::test_utils; // TODO add more theory json files -const THEORY_FIXTURES: &[&str] = &["GraphOfGraphsRealm.json", "GraphRealm.json"]; +const THEORY_FIXTURES: &[&str] = &[ + "GraphRealm.json", + "GraphOfGraphsRealm.json", + "TriangleRealm.json", + "TransitiveClosureRealm.json", +]; #[test] fn deserialises_all_theory_fixtures() { From 7e2585aca2f8e2ecd695b653bb6ef8e3aaa4fee7 Mon Sep 17 00:00:00 2001 From: Leo Stewen Date: Thu, 10 Sep 2026 08:00:52 +0200 Subject: [PATCH 40/42] [coln-query] fix: repair existing tests after updated FLIR --- packages/coln-query/justfile | 2 +- packages/coln-query/src/api/mod.rs | 4 ++-- packages/coln-query/src/api/query.rs | 4 ++-- packages/coln-query/src/test_utils.rs | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/coln-query/justfile b/packages/coln-query/justfile index 37b0f633..68e2eaa9 100644 --- a/packages/coln-query/justfile +++ b/packages/coln-query/justfile @@ -26,7 +26,7 @@ lint-check: # Run tests with stdout and stderr suppressed. test *TESTS: - cargo nextest run -p {{ crate }} --all-targets {{ TESTS }} + cargo nextest run -p {{ crate }} --all-targets --no-fail-fast {{ TESTS }} # As of now nextest does not support doc tests, so we fallback to # cargo test to run them. cargo test --doc -p {{ crate }} {{ TESTS }} diff --git a/packages/coln-query/src/api/mod.rs b/packages/coln-query/src/api/mod.rs index d04a6792..43b11438 100644 --- a/packages/coln-query/src/api/mod.rs +++ b/packages/coln-query/src/api/mod.rs @@ -391,7 +391,7 @@ mod test { let violations = violations.into_inner(); assert_eq!(violations.len(), 1); let violation = &violations[0]; - assert_eq!(violation.for_entity().id(), "Graph.E.foreignKey"); + assert_eq!(violation.for_entity().id(), "GraphRealm.root.E.foreignKey"); assert_eq!(violation.delta().len(), 3); let mut tx3 = Tx::empty(); @@ -404,7 +404,7 @@ mod test { let violations = violations.into_inner(); assert_eq!(violations.len(), 1); let violation = &violations[0]; - assert_eq!(violation.for_entity().id(), "Graph.E.foreignKey"); + assert_eq!(violation.for_entity().id(), "GraphRealm.root.E.foreignKey"); assert_eq!(violation.delta().len(), 1); Ok(()) diff --git a/packages/coln-query/src/api/query.rs b/packages/coln-query/src/api/query.rs index d82eec4f..13073730 100644 --- a/packages/coln-query/src/api/query.rs +++ b/packages/coln-query/src/api/query.rs @@ -1535,13 +1535,13 @@ mod tests { #[test] fn graph_flir() { - let program = translate_json_flir("Graph.json"); + let program = translate_json_flir("GraphRealm.json"); println!("{}", program.to_tree()); } #[test] fn graph_of_graphs_flir() { - let program = translate_json_flir("GraphOfGraphs.json"); + let program = translate_json_flir("GraphOfGraphsRealm.json"); println!("{}", program.to_tree()); } } diff --git a/packages/coln-query/src/test_utils.rs b/packages/coln-query/src/test_utils.rs index a92a4bf3..226ef3d2 100644 --- a/packages/coln-query/src/test_utils.rs +++ b/packages/coln-query/src/test_utils.rs @@ -276,7 +276,7 @@ pub mod graph_flir { } impl JsonFlir for GraphFlir { - const FILENAME: &'static str = "Graph.json"; + const FILENAME: &'static str = "GraphRealm.json"; } pub trait Entity { @@ -318,7 +318,7 @@ pub mod graph_flir { } impl Entity for Vertex { - const NAME: &'static str = "Graph.V"; + const NAME: &'static str = "GraphRealm.root.V"; fn to_row(&self) -> TupleValue { [ @@ -372,7 +372,7 @@ pub mod graph_flir { } impl Entity for Edge { - const NAME: &'static str = "Graph.E"; + const NAME: &'static str = "GraphRealm.root.E"; fn to_row(&self) -> TupleValue { [ From 37b544bb95631e334bc7d876264bd43f03eb707b Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Thu, 10 Sep 2026 10:32:48 +0100 Subject: [PATCH 41/42] bipartite transitive closure --- .../test/golden/bipartite-trans-closure.coln | 19 ++++++ .../tests/data/BipartiteGraphRealm.json | 1 + .../tests/data/BipartiteGraphRealm.pretty | 58 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 packages/coln-compiler/test/golden/bipartite-trans-closure.coln create mode 100644 packages/coln-flir-rs/tests/data/BipartiteGraphRealm.json create mode 100644 packages/coln-flir-rs/tests/data/BipartiteGraphRealm.pretty diff --git a/packages/coln-compiler/test/golden/bipartite-trans-closure.coln b/packages/coln-compiler/test/golden/bipartite-trans-closure.coln new file mode 100644 index 00000000..18919f9e --- /dev/null +++ b/packages/coln-compiler/test/golden/bipartite-trans-closure.coln @@ -0,0 +1,19 @@ +theory BipartiteGraph := sig + red : Set + blue : Set + red-blue : red -> blue -> Set + blue-red : blue -> red -> Set +end + +theory BipartiteConnection (^i G : BipartiteGraph) := sig + red-red : G.red -> G.red -> Prop + blue-blue : G.blue -> G.blue -> Prop + red/refl : (v : G.red) -> red-red v v + blue/refl : (v : G.blue) -> blue-blue v v + red/trans : (v0 : G.red) -> (v1 : G.red) -> (w0 : G.blue) -> (w1 : G.blue) -> G.red-blue v0 w0 -> blue-blue w0 w1 -> G.blue-red w1 v1 -> red-red v0 v1 + blue/trans : (v0 : G.blue) -> (v1 : G.blue) -> (w0 : G.red) -> (w1 : G.red) -> G.blue-red v0 w0 -> red-red w0 w1 -> G.red-blue w1 v1 -> blue-blue v0 v1 +end + +realm BipartiteGraphRealm @ BipartiteGraph + ind def connection-info : BipartiteConnection root := init (BipartiteConnection root) +end diff --git a/packages/coln-flir-rs/tests/data/BipartiteGraphRealm.json b/packages/coln-flir-rs/tests/data/BipartiteGraphRealm.json new file mode 100644 index 00000000..c9fc3b38 --- /dev/null +++ b/packages/coln-flir-rs/tests/data/BipartiteGraphRealm.json @@ -0,0 +1 @@ +{"entities":[{"path":[["BipartiteGraphRealm"],["root"],["red"]],"value":{"entityVariant":{"tag":"table"},"columns":[],"primaryKey":null}},{"path":[["BipartiteGraphRealm"],["root"],["blue"]],"value":{"entityVariant":{"tag":"table"},"columns":[],"primaryKey":null}},{"path":[["BipartiteGraphRealm"],["root"],["red-blue"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}}],"primaryKey":null}},{"path":[["BipartiteGraphRealm"],["root"],["blue-red"]],"value":{"entityVariant":{"tag":"table"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}}],"primaryKey":null}},{"path":[["BipartiteGraphRealm"],["init"],["connection-info"],["red-red"]],"value":{"entityVariant":{"tag":"view","materialization":"memoized"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}}],"primaryKey":[0,1]}},{"path":[["BipartiteGraphRealm"],["init"],["connection-info"],["blue-blue"]],"value":{"entityVariant":{"tag":"view","materialization":"memoized"},"columns":[{"path":[["a"]],"type":{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}},{"path":[["b"]],"type":{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}}],"primaryKey":[0,1]}}],"definitions":[{"path":[["BipartiteGraphRealm"],["init"],["connection-info"],["red","refl"]],"value":{"vars":[[[["v"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red"]],"rowId":{"tag":"var","index":0},"values":[]}}],"definand":[["BipartiteGraphRealm"],["init"],["connection-info"],["red-red"]],"arguments":[{"tag":"var","index":0},{"tag":"var","index":0}]}},{"path":[["BipartiteGraphRealm"],["init"],["connection-info"],["blue","refl"]],"value":{"vars":[[[["v"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue"]],"rowId":{"tag":"var","index":0},"values":[]}}],"definand":[["BipartiteGraphRealm"],["init"],["connection-info"],["blue-blue"]],"arguments":[{"tag":"var","index":0},{"tag":"var","index":0}]}},{"path":[["BipartiteGraphRealm"],["init"],["connection-info"],["red","trans"]],"value":{"vars":[[[["v0"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}],[[["v1"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}],[[["w0"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}],[[["w1"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}],[[["a"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red-blue"]]}],[[["c"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue-red"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue"]],"rowId":{"tag":"var","index":2},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue"]],"rowId":{"tag":"var","index":3},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red-blue"]],"rowId":{"tag":"var","index":4},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":2}}]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["init"],["connection-info"],["blue-blue"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":2}},{"column":1,"term":{"tag":"var","index":3}}]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue-red"]],"rowId":{"tag":"var","index":5},"values":[{"column":0,"term":{"tag":"var","index":3}},{"column":1,"term":{"tag":"var","index":1}}]}}],"definand":[["BipartiteGraphRealm"],["init"],["connection-info"],["red-red"]],"arguments":[{"tag":"var","index":0},{"tag":"var","index":1}]}},{"path":[["BipartiteGraphRealm"],["init"],["connection-info"],["blue","trans"]],"value":{"vars":[[[["v0"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}],[[["v1"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}],[[["w0"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}],[[["w1"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}],[[["a"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue-red"]]}],[[["c"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red-blue"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue"]],"rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red"]],"rowId":{"tag":"var","index":2},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red"]],"rowId":{"tag":"var","index":3},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue-red"]],"rowId":{"tag":"var","index":4},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":2}}]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["init"],["connection-info"],["red-red"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":2}},{"column":1,"term":{"tag":"var","index":3}}]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red-blue"]],"rowId":{"tag":"var","index":5},"values":[{"column":0,"term":{"tag":"var","index":3}},{"column":1,"term":{"tag":"var","index":1}}]}}],"definand":[["BipartiteGraphRealm"],["init"],["connection-info"],["blue-blue"]],"arguments":[{"tag":"var","index":0},{"tag":"var","index":1}]}}],"rules":[{"path":[["BipartiteGraphRealm"],["root"],["red"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[],"antecedents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red"]],"rowId":null,"values":[]}}],"consequents":[]}},{"path":[["BipartiteGraphRealm"],["root"],["blue"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[],"antecedents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue"]],"rowId":null,"values":[]}}],"consequents":[]}},{"path":[["BipartiteGraphRealm"],["root"],["red-blue"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}],[[["b"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red-blue"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue"]],"rowId":{"tag":"var","index":1},"values":[]}}]}},{"path":[["BipartiteGraphRealm"],["root"],["blue-red"],["foreignKey"]],"value":{"ruleVariant":"enforced","vars":[[[["a"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["blue"]]}],[[["b"]],{"tag":"rowId","path":[["BipartiteGraphRealm"],["root"],["red"]]}]],"antecedents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue-red"]],"rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}}],"consequents":[{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["blue"]],"rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":[["BipartiteGraphRealm"],["root"],["red"]],"rowId":{"tag":"var","index":1},"values":[]}}]}}]} \ No newline at end of file diff --git a/packages/coln-flir-rs/tests/data/BipartiteGraphRealm.pretty b/packages/coln-flir-rs/tests/data/BipartiteGraphRealm.pretty new file mode 100644 index 00000000..038b0381 --- /dev/null +++ b/packages/coln-flir-rs/tests/data/BipartiteGraphRealm.pretty @@ -0,0 +1,58 @@ +flatrealm + entities + table ℜ.root.red := [] + table ℜ.root.blue := [] + table ℜ.root.red-blue := [.a : ℜ.root.red, .b : ℜ.root.blue] + table ℜ.root.blue-red := [.a : ℜ.root.blue, .b : ℜ.root.red] + view ℜ.init.connection-info.red-red := [ + .a : ℜ.root.red, + .b : ℜ.root.red + ] primarykey [.a, .b] + view ℜ.init.connection-info.blue-blue := [ + .a : ℜ.root.blue, + .b : ℜ.root.blue + ] primarykey [.a, .b] + end + definitions + chased ℜ.init.connection-info.red/refl v := v ∈ ℜ.root.red [] ⊢ ℜ.init.connection-info.red-red [ + .a ↦ v, + .b ↦ v + ] + chased ℜ.init.connection-info.blue/refl v := v ∈ ℜ.root.blue [] ⊢ ℜ.init.connection-info.blue-blue [ + .a ↦ v, + .b ↦ v + ] + chased ℜ.init.connection-info.red/trans v0 v1 w0 w1 a c := v0 ∈ ℜ.root.red [] ∧ v1 ∈ ℜ.root.red [] ∧ w0 ∈ ℜ.root.blue [] ∧ w1 ∈ ℜ.root.blue [] ∧ a ∈ ℜ.root.red-blue [ + .a ↦ v0, + .b ↦ w0 + ] ∧ ℜ.init.connection-info.blue-blue [ + .a ↦ w0, + .b ↦ w1 + ] ∧ c ∈ ℜ.root.blue-red [ + .a ↦ w1, + .b ↦ v1 + ] ⊢ ℜ.init.connection-info.red-red [.a ↦ v0, .b ↦ v1] + chased ℜ.init.connection-info.blue/trans v0 v1 w0 w1 a c := v0 ∈ ℜ.root.blue [] ∧ v1 ∈ ℜ.root.blue [] ∧ w0 ∈ ℜ.root.red [] ∧ w1 ∈ ℜ.root.red [] ∧ a ∈ ℜ.root.blue-red [ + .a ↦ v0, + .b ↦ w0 + ] ∧ ℜ.init.connection-info.red-red [ + .a ↦ w0, + .b ↦ w1 + ] ∧ c ∈ ℜ.root.red-blue [ + .a ↦ w1, + .b ↦ v1 + ] ⊢ ℜ.init.connection-info.blue-blue [.a ↦ v0, .b ↦ v1] + end + rules + enforced ℜ.root.red.foreignKey := ℜ.root.red [] ⊢ ⊤ + enforced ℜ.root.blue.foreignKey := ℜ.root.blue [] ⊢ ⊤ + enforced ℜ.root.red-blue.foreignKey a b := ℜ.root.red-blue [ + .a ↦ a, + .b ↦ b + ] ⊢ a ∈ ℜ.root.red [] ∧ b ∈ ℜ.root.blue [] + enforced ℜ.root.blue-red.foreignKey a b := ℜ.root.blue-red [ + .a ↦ a, + .b ↦ b + ] ⊢ a ∈ ℜ.root.blue [] ∧ b ∈ ℜ.root.red [] + end +end \ No newline at end of file From ee76eaf9f1a17e4702c78688b4dc473a90d7dde4 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Thu, 10 Sep 2026 15:01:10 +0100 Subject: [PATCH 42/42] table names are now just strings --- .../src/Coln/Backend/TypeScript/Generate.hs | 510 +++++++++--------- packages/coln-compiler/src/Coln/Common.hs | 7 +- .../coln-compiler/src/Coln/Core/Params.hs | 10 +- packages/coln-compiler/src/Coln/Core/Print.hs | 3 +- .../coln-compiler/src/Coln/FLIR/Flatten.hs | 6 +- packages/coln-compiler/src/Coln/FLIR/Top.hs | 14 +- packages/coln-compiler/src/Coln/FLIR/Value.hs | 41 +- packages/coln-compiler/src/Coln/MIR/Layout.hs | 11 +- packages/coln-compiler/src/Coln/MIR/Top.hs | 8 +- packages/coln-compiler/src/Coln/SIR/Cache.hs | 12 +- .../coln-compiler/src/Coln/SIR/Separate.hs | 5 +- packages/coln-compiler/src/Coln/SIR/Syntax.hs | 15 +- packages/coln-compiler/src/Coln/SIR/Top.hs | 10 +- packages/coln-compiler/src/Coln/Top.hs | 6 +- packages/coln-compiler/test/golden/graph.coln | 10 + .../coln-compiler/typescript-model/graph.ts | 16 +- .../typescript-model/runtime/flatten.ts | 5 +- .../typescript-model/runtime/set.ts | 35 +- .../typescript-model/runtime/store.ts | 12 +- .../typescript-model/runtime/types.ts | 6 +- packages/coln-flir-rs/src/ir/mod.rs | 44 +- packages/coln-flir-rs/src/ir/path.rs | 192 ------- .../coln-flir-rs/tests/data/GraphRealm.json | 104 +--- .../coln-flir-rs/tests/data/GraphRealm.pretty | 82 ++- packages/coln-query/src/api/query.rs | 4 +- packages/coln-rpc/src/rust/api.rs | 13 +- packages/coln-store/src/commit/wire/prim.rs | 27 +- packages/coln-store/src/repl/exe/sql.rs | 4 +- packages/coln-store/src/repl/mod.rs | 36 +- packages/coln-store/src/solver/compile.rs | 12 +- packages/fnotation/src/FNotation/Pretty.hs | 1 + packages/fnotation/src/FNotation/Trees.hs | 5 + 32 files changed, 524 insertions(+), 742 deletions(-) delete mode 100644 packages/coln-flir-rs/src/ir/path.rs diff --git a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs index 72632638..c89980a8 100644 --- a/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs +++ b/packages/coln-compiler/src/Coln/Backend/TypeScript/Generate.hs @@ -4,266 +4,266 @@ module Coln.Backend.TypeScript.Generate where -import Control.Monad.State +-- import Control.Monad.State -- import Data.Aeson qualified as AE -import Data.Foldable (foldlM) +-- import Data.Foldable (foldlM) -- import Data.Foldable qualified as F -- import Data.Map.Ordered qualified as OMap -import Data.Set qualified as Set -import Data.String (IsString (..)) -import Data.Text.Lazy qualified as TL -import Data.Text.Lazy.IO qualified as TLIO -import Prettyprinter -import Prettyprinter.Render.Text -import System.FilePath - -import Coln.Backend.TypeScript.AST qualified as TS -import Coln.Backend.TypeScript.Assemble (asm) -import Coln.Backend.TypeScript.Params -import Coln.Common - -import Coln.Core.Params -import Coln.Core.Readback -import Coln.Core.Syntax qualified as S -import Coln.Core.Value qualified as V -import Coln.FLIR.Flatten qualified as FLIR -import Coln.FLIR.Value qualified as FLIR -import Coln.SIR.Realm qualified as SIR -import Coln.SIR.Syntax qualified as SIR - -mangle :: Name -> TS.Id -mangle = TS.Id . mangleToDoc - -tyFromHead :: Access -> V.Head -> TS.Ty -tyFromHead access (V.GlobalVar x _) = - TS.TyConst (TS.QId [mangle x] (fromString (show access))) -tyFromHead access (V.LocalVar _) = TS.runtime $ ColnRef access - -genTy :: Access -> CtxLen -> V.Ty N -> TS.Ty -genTy access n = \case - V.U (SetU; PropU) -> TS.runtime (ColnSet access) - V.Function ft -> do - let v = V.local (FId n) ft.dom - TS.Fun (TS.Binding (TS.Id "x") (TS.runtime Value)) (genTy access (n + 1) (V.appClo ft.cod v)) - V.Decode n -> tyFromHead access n.head - V.BuiltinTy _ -> TS.runtime $ ColnRef access - _ -> error "not yet supported" - -genInterface :: Access -> CtxLen -> V.Ty D -> TS.Interface -genInterface access n = \case - V.Record rt -> do - let name = fromString $ show access - let extendsName = fromString . show <$> extends access - TS.Interface name extendsName (go n rt.capture (toList rt.fieldTypes)) - where - go _ _ [] = [] - go n' vs ((x, f) : rest) = do - let a = f vs - let v = V.local (FId n') a - let bnd = TS.Binding (mangle x) (genTy access n' a) - bnd : go (n' + 1) (V.LSnoc vs v) rest - -class TrackGlobals a where - trackGlobals :: a -> State (Set.Set Name) () - -instance (TrackGlobals (f c)) => TrackGlobals (S.Abs f c) where - trackGlobals (S.Abs _ body) = trackGlobals body - trackGlobals (S.AbsConst body) = trackGlobals body - -instance (TrackGlobals a) => TrackGlobals (Name, a) where - trackGlobals (_, t) = trackGlobals t - -instance TrackGlobals (S.El c) where - trackGlobals = \case - S.LocalVar _ -> pure () - S.GlobalVar x _ -> modify (Set.insert x) - S.Code _ a -> trackGlobals a - S.Lam _ dom body -> do - trackGlobals dom - trackGlobals body - S.App _ t0 t1 -> do - trackGlobals t0 - trackGlobals t1 - S.Cons _ ts -> mapM_ trackGlobals (toList ts) - S.Proj _ t _ -> trackGlobals t - S.Init _ -> pure () - S.Lit _ -> pure () - S.Is t -> trackGlobals t - -instance TrackGlobals (S.Ty c) where - trackGlobals = \case - S.U _ -> pure () - S.Decode _ t -> trackGlobals t - S.Function ft -> do - trackGlobals ft.dom - trackGlobals ft.cod - S.Record rt -> mapM_ trackGlobals (toList rt.fieldTypes) - S.Eq et -> do - trackGlobals et.lhs - trackGlobals et.rhs - S.BuiltinTy _ -> pure () - S.IsTy a -> trackGlobals a - -genTypeDef :: Access -> CtxLen -> V.Ty N -> TS.TypeDef -genTypeDef access n a = TS.TypeDef (fromShow access) (genTy access n a) - -genEntryModule :: [TS.Import] -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module -genEntryModule imports a ev = go 0 a ev - where - go :: CtxLen -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module - go n (V.U TheoryU) ev' = do - let definitions = for accessLevels $ \access -> - case V.ebind V.decode ev' of - V.Become a -> TS.DTypeDef $ genTypeDef access n a - V.Describe a -> TS.DInterface $ genInterface access n a - V.BecomeWith _ -> panic "can't lower becomewith yet" - Just $ TS.Module imports (TS.Exported <$> definitions) - go n (V.Function ft) ev' = do - let v = V.local (FId n) ft.dom - go (n + 1) (V.appClo ft.cod v) (V.ebind (flip (V.app ft.variant) v) ev') - go _ _ _ = Nothing - -tableNameDoc :: TableName -> DDoc -tableNameDoc tn = concatWith (surround dot) (dpretty <$> (tn.realm : toList tn.path)) - -data FlatParams = FlatParams - { paramVals :: Bwd TS.El - , numParams :: Int - } - -allocParams :: TS.El -> SIR.Shape -> State FlatParams FLIR.Els -allocParams v = \case - SIR.Tuple d -> do - FLIR.Cons <$> mapWithKeyM (\x sh -> allocParams (TS.Proj v (mangle x)) sh) d - SIR.Scalar _ -> state \p -> - ( FLIR.Scalar (FLIR.Param (FId p.numParams)) - , p{paramVals = p.paramVals :> v, numParams = p.numParams + 1} - ) - SIR.Unstored -> pure FLIR.Erased - -data TSEnv = TSEnv - { tsLocals :: Bwd TS.El - , usedNames :: Set.Set Name - , flatParams :: FlatParams - , flirLocals :: FLIR.Locals - } - -emptyTSEnv :: TSEnv -emptyTSEnv = TSEnv BwdNil Set.empty (FlatParams BwdNil 0) BwdNil - -reconstructEl :: FlatParams -> FLIR.El -> TS.El -reconstructEl e = \case - FLIR.LocalVar (FId i) -> TS.Index (TS.Var "result") i - FLIR.Lit l -> TS.Lit l - FLIR.Param (FId i) -> elemAt e.paramVals (BId (e.numParams - i - 1)) - -reconstructEls :: FlatParams -> FLIR.Els -> TS.El -reconstructEls e = \case - FLIR.Scalar v -> reconstructEl e v - FLIR.Cons d -> TS.Object [(mangle x, reconstructEls e t) | (x, t) <- toList d] - FLIR.Erased -> TS.Null - -genQuery :: Access -> TSEnv -> SIR.Query -> TS.El -genQuery _access e q = do - let ((v, mainProps), vars, auxProps) = FLIR.runFlatM $ do - v <- FLIR.freshAt (BwdNil :> "result") q.shape - mainprops <- FLIR.app e.flirLocals q.pred v - pure (v, mainprops) - let query = FLIR.Query vars (toList (mainProps <> auxProps)) - let flir = TS.String (undefined query) - -- TODO: should make sure "result" is fresh - let reconstruct = - TS.Lam - (TS.Binding "result" (TS.ListTy (TS.runtime Value))) - (TS.Block [] (Just (reconstructEls e.flatParams v))) - TS.New (TS.Const (TS.runtime Query)) [flir, reconstruct] - -varName :: SIR.Abs a -> Set.Set Name -> Name -varName (SIR.Abs (Just x) _) xs = case Set.member x xs of - True -> freshNameFor xs - False -> x -varName _ xs = freshNameFor xs - -genAbs :: Access -> TSEnv -> SIR.Abs (SIR.El l) -> (Name, TS.El) -genAbs access e (SIR.Abs mx body) = do - let x = freshNameWithPref e.usedNames mx - let e' = - e - { tsLocals = e.tsLocals :> TS.Var (mangle x) - , usedNames = Set.insert x e.usedNames - } - (x, genEl access e' body) -genAbs access e (SIR.AbsConst body) = do - let x = freshNameFor e.usedNames - let e' = e{usedNames = Set.insert x e.usedNames} - (x, genEl access e' body) - -genEl :: Access -> TSEnv -> SIR.El l -> TS.El -genEl access e = \case - SIR.LiftEl t -> genEl access e t - SIR.Var i -> elemAt e.tsLocals i - -- SIR.Single q -> TS.MethodCall (genQuery access e q) "single" [] - SIR.Proj t x -> TS.Proj (genEl access e t) (mangle x) - -- SIR.Multi _ q -> TS.MethodCall (genQuery access e q) "multi" [] - SIR.Lam _dom abs -> do - let (x, body) = genAbs access e abs - TS.Lam - (TS.Binding (mangle x) (TS.runtime Value)) - (TS.Block [] (Just body)) - SIR.Cons fields -> - TS.Object [(mangle x, genEl access e t) | (x, t) <- toList fields] - SIR.Lit l -> TS.Lit l - SIR.Erased -> TS.Null - -genRealmConstructor :: Access -> SIR.Realm -> TS.Constructor -genRealmConstructor access r = do - let args = case access of - View -> - [ TS.Binding "store" (TS.runtime StoreHandle) - ] - Transaction -> - [ TS.Binding "store" (TS.runtime StoreHandle) - , TS.Binding "transaction" (TS.runtime TransactionHandle) - ] - let superCall = case extends access of - Just _ -> [TS.Expr (TS.Call (TS.Var "super") [TS.Var "store"])] - Nothing -> [] - let body = - TS.Block - (superCall ++ [TS.Assign (TS.QId ["this"] "root") (genEl access emptyTSEnv r.root)]) - Nothing - TS.Constructor args body - -genRealmClass :: Access -> SIR.Realm -> TS.Class -genRealmClass access r = - TS.Class - (fromShow access) - Nothing - (fromShow <$> extends access) - [TS.Binding "root" (genTy access 0 r.rootType)] - (genRealmConstructor access r) - -genRealmModule :: [TS.Import] -> SIR.Realm -> TS.Module -genRealmModule imports r = do - let classes = for accessLevels $ \access -> TS.DClass $ genRealmClass access r - TS.Module imports (TS.Exported <$> classes) - -render :: DDoc -> TL.Text -render = renderLazy . layoutPretty defaultLayoutOptions - -writeModule :: FilePath -> Name -> TS.Module -> IO () -writeModule outdir x mod = do - let fn = outdir TS.idToString (mangle x) <> ".ts" - let content = render $ asm mod - TLIO.writeFile fn content - -runtimeImport :: TS.Import -runtimeImport = TS.ImportQualified "runtime" "@coln-project/runtime" - -forAccM :: (Monad m) => [b] -> a -> (a -> b -> m a) -> m a -forAccM bs init f = foldlM f init bs +-- import Data.Set qualified as Set +-- import Data.String (IsString (..)) +-- import Data.Text.Lazy qualified as TL +-- import Data.Text.Lazy.IO qualified as TLIO +-- import Prettyprinter +-- import Prettyprinter.Render.Text +-- import System.FilePath + +-- import Coln.Backend.TypeScript.AST qualified as TS +-- import Coln.Backend.TypeScript.Assemble (asm) +-- import Coln.Backend.TypeScript.Params +-- import Coln.Common + +-- import Coln.Core.Params +-- import Coln.Core.Readback +-- import Coln.Core.Syntax qualified as S +-- import Coln.Core.Value qualified as V +-- import Coln.FLIR.Flatten qualified as FLIR +-- import Coln.FLIR.Value qualified as FLIR +-- import Coln.SIR.Realm qualified as SIR +-- import Coln.SIR.Syntax qualified as SIR + +-- mangle :: Name -> TS.Id +-- mangle = TS.Id . mangleToDoc + +-- tyFromHead :: Access -> V.Head -> TS.Ty +-- tyFromHead access (V.GlobalVar x _) = +-- TS.TyConst (TS.QId [mangle x] (fromString (show access))) +-- tyFromHead access (V.LocalVar _) = TS.runtime $ ColnRef access + +-- genTy :: Access -> CtxLen -> V.Ty N -> TS.Ty +-- genTy access n = \case +-- V.U (SetU; PropU) -> TS.runtime (ColnSet access) +-- V.Function ft -> do +-- let v = V.local (FId n) ft.dom +-- TS.Fun (TS.Binding (TS.Id "x") (TS.runtime Value)) (genTy access (n + 1) (V.appClo ft.cod v)) +-- V.Decode n -> tyFromHead access n.head +-- V.BuiltinTy _ -> TS.runtime $ ColnRef access +-- _ -> error "not yet supported" + +-- genInterface :: Access -> CtxLen -> V.Ty D -> TS.Interface +-- genInterface access n = \case +-- V.Record rt -> do +-- let name = fromString $ show access +-- let extendsName = fromString . show <$> extends access +-- TS.Interface name extendsName (go n rt.capture (toList rt.fieldTypes)) +-- where +-- go _ _ [] = [] +-- go n' vs ((x, f) : rest) = do +-- let a = f vs +-- let v = V.local (FId n') a +-- let bnd = TS.Binding (mangle x) (genTy access n' a) +-- bnd : go (n' + 1) (V.LSnoc vs v) rest + +-- class TrackGlobals a where +-- trackGlobals :: a -> State (Set.Set Name) () + +-- instance (TrackGlobals (f c)) => TrackGlobals (S.Abs f c) where +-- trackGlobals (S.Abs _ body) = trackGlobals body +-- trackGlobals (S.AbsConst body) = trackGlobals body + +-- instance (TrackGlobals a) => TrackGlobals (Name, a) where +-- trackGlobals (_, t) = trackGlobals t + +-- instance TrackGlobals (S.El c) where +-- trackGlobals = \case +-- S.LocalVar _ -> pure () +-- S.GlobalVar x _ -> modify (Set.insert x) +-- S.Code _ a -> trackGlobals a +-- S.Lam _ dom body -> do +-- trackGlobals dom +-- trackGlobals body +-- S.App _ t0 t1 -> do +-- trackGlobals t0 +-- trackGlobals t1 +-- S.Cons _ ts -> mapM_ trackGlobals (toList ts) +-- S.Proj _ t _ -> trackGlobals t +-- S.Init _ -> pure () +-- S.Lit _ -> pure () +-- S.Is t -> trackGlobals t + +-- instance TrackGlobals (S.Ty c) where +-- trackGlobals = \case +-- S.U _ -> pure () +-- S.Decode _ t -> trackGlobals t +-- S.Function ft -> do +-- trackGlobals ft.dom +-- trackGlobals ft.cod +-- S.Record rt -> mapM_ trackGlobals (toList rt.fieldTypes) +-- S.Eq et -> do +-- trackGlobals et.lhs +-- trackGlobals et.rhs +-- S.BuiltinTy _ -> pure () +-- S.IsTy a -> trackGlobals a + +-- genTypeDef :: Access -> CtxLen -> V.Ty N -> TS.TypeDef +-- genTypeDef access n a = TS.TypeDef (fromShow access) (genTy access n a) + +-- genEntryModule :: [TS.Import] -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module +-- genEntryModule imports a ev = go 0 a ev +-- where +-- go :: CtxLen -> V.Ty N -> V.Evaluation V.El D -> Maybe TS.Module +-- go n (V.U TheoryU) ev' = do +-- let definitions = for accessLevels $ \access -> +-- case V.ebind V.decode ev' of +-- V.Become a -> TS.DTypeDef $ genTypeDef access n a +-- V.Describe a -> TS.DInterface $ genInterface access n a +-- V.BecomeWith _ -> panic "can't lower becomewith yet" +-- Just $ TS.Module imports (TS.Exported <$> definitions) +-- go n (V.Function ft) ev' = do +-- let v = V.local (FId n) ft.dom +-- go (n + 1) (V.appClo ft.cod v) (V.ebind (flip (V.app ft.variant) v) ev') +-- go _ _ _ = Nothing + +-- tableNameDoc :: TableName -> DDoc +-- tableNameDoc tn = concatWith (surround dot) (dpretty <$> (tn.realm : toList tn.path)) + +-- data FlatParams = FlatParams +-- { paramVals :: Bwd TS.El +-- , numParams :: Int +-- } + +-- allocParams :: TS.El -> SIR.Shape -> State FlatParams FLIR.Els +-- allocParams v = \case +-- SIR.Tuple d -> do +-- FLIR.Cons <$> mapWithKeyM (\x sh -> allocParams (TS.Proj v (mangle x)) sh) d +-- SIR.Scalar _ -> state \p -> +-- ( FLIR.Scalar (FLIR.Param (FId p.numParams)) +-- , p{paramVals = p.paramVals :> v, numParams = p.numParams + 1} +-- ) +-- SIR.Unstored -> pure FLIR.Erased + +-- data TSEnv = TSEnv +-- { tsLocals :: Bwd TS.El +-- , usedNames :: Set.Set Name +-- , flatParams :: FlatParams +-- , flirLocals :: FLIR.Locals +-- } + +-- emptyTSEnv :: TSEnv +-- emptyTSEnv = TSEnv BwdNil Set.empty (FlatParams BwdNil 0) BwdNil + +-- reconstructEl :: FlatParams -> FLIR.El -> TS.El +-- reconstructEl e = \case +-- FLIR.LocalVar (FId i) -> TS.Index (TS.Var "result") i +-- FLIR.Lit l -> TS.Lit l +-- FLIR.Param (FId i) -> elemAt e.paramVals (BId (e.numParams - i - 1)) + +-- reconstructEls :: FlatParams -> FLIR.Els -> TS.El +-- reconstructEls e = \case +-- FLIR.Scalar v -> reconstructEl e v +-- FLIR.Cons d -> TS.Object [(mangle x, reconstructEls e t) | (x, t) <- toList d] +-- FLIR.Erased -> TS.Null + +-- genQuery :: Access -> TSEnv -> SIR.Query -> TS.El +-- genQuery _access e q = do +-- let ((v, mainProps), vars, auxProps) = FLIR.runFlatM $ do +-- v <- FLIR.freshAt (BwdNil :> "result") q.shape +-- mainprops <- FLIR.app e.flirLocals q.pred v +-- pure (v, mainprops) +-- let query = FLIR.Query vars (toList (mainProps <> auxProps)) +-- let flir = TS.String (undefined query) +-- -- TODO: should make sure "result" is fresh +-- let reconstruct = +-- TS.Lam +-- (TS.Binding "result" (TS.ListTy (TS.runtime Value))) +-- (TS.Block [] (Just (reconstructEls e.flatParams v))) +-- TS.New (TS.Const (TS.runtime Query)) [flir, reconstruct] + +-- varName :: SIR.Abs a -> Set.Set Name -> Name +-- varName (SIR.Abs (Just x) _) xs = case Set.member x xs of +-- True -> freshNameFor xs +-- False -> x +-- varName _ xs = freshNameFor xs + +-- genAbs :: Access -> TSEnv -> SIR.Abs (SIR.El l) -> (Name, TS.El) +-- genAbs access e (SIR.Abs mx body) = do +-- let x = freshNameWithPref e.usedNames mx +-- let e' = +-- e +-- { tsLocals = e.tsLocals :> TS.Var (mangle x) +-- , usedNames = Set.insert x e.usedNames +-- } +-- (x, genEl access e' body) +-- genAbs access e (SIR.AbsConst body) = do +-- let x = freshNameFor e.usedNames +-- let e' = e{usedNames = Set.insert x e.usedNames} +-- (x, genEl access e' body) + +-- genEl :: Access -> TSEnv -> SIR.El l -> TS.El +-- genEl access e = \case +-- SIR.LiftEl t -> genEl access e t +-- SIR.Var i -> elemAt e.tsLocals i +-- -- SIR.Single q -> TS.MethodCall (genQuery access e q) "single" [] +-- SIR.Proj t x -> TS.Proj (genEl access e t) (mangle x) +-- -- SIR.Multi _ q -> TS.MethodCall (genQuery access e q) "multi" [] +-- SIR.Lam _dom abs -> do +-- let (x, body) = genAbs access e abs +-- TS.Lam +-- (TS.Binding (mangle x) (TS.runtime Value)) +-- (TS.Block [] (Just body)) +-- SIR.Cons fields -> +-- TS.Object [(mangle x, genEl access e t) | (x, t) <- toList fields] +-- SIR.Lit l -> TS.Lit l +-- SIR.Erased -> TS.Null + +-- genRealmConstructor :: Access -> SIR.Realm -> TS.Constructor +-- genRealmConstructor access r = do +-- let args = case access of +-- View -> +-- [ TS.Binding "store" (TS.runtime StoreHandle) +-- ] +-- Transaction -> +-- [ TS.Binding "store" (TS.runtime StoreHandle) +-- , TS.Binding "transaction" (TS.runtime TransactionHandle) +-- ] +-- let superCall = case extends access of +-- Just _ -> [TS.Expr (TS.Call (TS.Var "super") [TS.Var "store"])] +-- Nothing -> [] +-- let body = +-- TS.Block +-- (superCall ++ [TS.Assign (TS.QId ["this"] "root") (genEl access emptyTSEnv r.root)]) +-- Nothing +-- TS.Constructor args body + +-- genRealmClass :: Access -> SIR.Realm -> TS.Class +-- genRealmClass access r = +-- TS.Class +-- (fromShow access) +-- Nothing +-- (fromShow <$> extends access) +-- [TS.Binding "root" (genTy access 0 r.rootType)] +-- (genRealmConstructor access r) + +-- genRealmModule :: [TS.Import] -> SIR.Realm -> TS.Module +-- genRealmModule imports r = do +-- let classes = for accessLevels $ \access -> TS.DClass $ genRealmClass access r +-- TS.Module imports (TS.Exported <$> classes) + +-- render :: DDoc -> TL.Text +-- render = renderLazy . layoutPretty defaultLayoutOptions + +-- writeModule :: FilePath -> Name -> TS.Module -> IO () +-- writeModule outdir x mod = do +-- let fn = outdir TS.idToString (mangle x) <> ".ts" +-- let content = render $ asm mod +-- TLIO.writeFile fn content + +-- runtimeImport :: TS.Import +-- runtimeImport = TS.ImportQualified "runtime" "@coln-project/runtime" + +-- forAccM :: (Monad m) => [b] -> a -> (a -> b -> m a) -> m a +-- forAccM bs init f = foldlM f init bs -- generate :: Globals -> FilePath -> IO () -- generate ge outdir = do diff --git a/packages/coln-compiler/src/Coln/Common.hs b/packages/coln-compiler/src/Coln/Common.hs index def5445e..2047ac4b 100644 --- a/packages/coln-compiler/src/Coln/Common.hs +++ b/packages/coln-compiler/src/Coln/Common.hs @@ -46,6 +46,7 @@ module Coln.Common ( mangleToString, fromShow, for, + renderText ) where @@ -69,8 +70,9 @@ import Data.Void import Diagnostician import FNotation (Name (..)) -import Prettyprinter (Pretty (..), defaultLayoutOptions, layoutPretty, (<+>)) +import Prettyprinter (Pretty (..), defaultLayoutOptions, layoutPretty, layoutCompact, (<+>)) import Prettyprinter.Render.String +import Prettyprinter.Render.Text import Prelude hiding (lookup) #ifdef DEBUG @@ -371,3 +373,6 @@ mangleToDoc x = mconcat [pretty s <> "_slash_" | s <- x.init] <> pretty x.last mangleToString :: Name -> String mangleToString = renderString . layoutPretty defaultLayoutOptions . mangleToDoc + +renderText :: DDoc -> Text +renderText = renderStrict . layoutCompact diff --git a/packages/coln-compiler/src/Coln/Core/Params.hs b/packages/coln-compiler/src/Coln/Core/Params.hs index 87c500d5..e74df790 100644 --- a/packages/coln-compiler/src/Coln/Core/Params.hs +++ b/packages/coln-compiler/src/Coln/Core/Params.hs @@ -9,6 +9,7 @@ import Coln.Common import GHC.Generics (Generic) import Prettyprinter + -- Level stuff (levels, universes, function variants) -------------------------------------------------------------------------------- @@ -185,11 +186,14 @@ type RealmId = Name type Path = Bwd Name -data TableName = TableName {realm :: RealmId, path :: Path} - deriving (Show, Eq, Ord) +newtype TableName = TableName { name :: Text } + deriving (Eq, Ord, Show) instance DPretty TableName where - dpretty tn = concatWith (surround dot) (dpretty <$> toList tn.path) + dpretty tn = pretty tn.name + +tableName :: Path -> TableName +tableName = TableName . renderText . concatWith (surround dot) . fmap dpretty . toList -- Mode -------------------------------------------------------------------------------- diff --git a/packages/coln-compiler/src/Coln/Core/Print.hs b/packages/coln-compiler/src/Coln/Core/Print.hs index 55e16140..e16058af 100644 --- a/packages/coln-compiler/src/Coln/Core/Print.hs +++ b/packages/coln-compiler/src/Coln/Core/Print.hs @@ -14,7 +14,6 @@ import Coln.Core.Params import Coln.Core.Readback import Coln.Core.Syntax import Coln.Frontend.Notation -import Data.List.NonEmpty (NonEmpty (..)) import Data.String (fromString) import Data.Text qualified as T import FNotation qualified as N @@ -41,7 +40,7 @@ instance ToNotation BId where go BwdNil _ _ = error $ "name " ++ show i ++ " not bound. ?names = " ++ (show $ toList xs) instance ToNotation TableName where - toNotation _ x = N.Group (N.Ident x.realm () :| [N.Field s () | s <- toList x.path]) + toNotation _ x = N.Raw x.name () instance ToNotation (El e) where toNotation xs = \case diff --git a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs index f8ed630f..ea8f0af3 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Flatten.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Flatten.hs @@ -63,7 +63,7 @@ freshAt p = \case S.Scalar t -> do aux <- get let i = aux.numVars - put $ aux{vars = (aux.vars :> (p, t)), numVars = (i + 1)} + put $ aux{vars = (aux.vars :> (tableName p, t)), numVars = (i + 1)} pure $ Scalar $ V.LocalVar $ FId i S.Tuple fields -> do fields' <- forM (toList fields) $ \(x, sh) -> freshAt (p :> x) sh @@ -139,9 +139,9 @@ instance Flatten S.Prop Props where v1 <- flatten l t1 pure $ equate sh v0 v1 -flattenColumn :: V.ColName -> S.Shape -> [(V.ColName, V.ColType)] +flattenColumn :: Path -> S.Shape -> [(V.ColName, V.ColType)] flattenColumn p = \case - S.Scalar t -> [(p, t)] + S.Scalar t -> [(tableName p, t)] S.Tuple d -> concat [flattenColumn (p :> x) t | (x, t) <- toList d] S.Unstored -> [] diff --git a/packages/coln-compiler/src/Coln/FLIR/Top.hs b/packages/coln-compiler/src/Coln/FLIR/Top.hs index 3c8742c0..72bc319a 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Top.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Top.hs @@ -12,13 +12,13 @@ import Coln.SIR.Realm qualified as SIR import Data.Map.Ordered qualified as OMap -trieToOMap :: RealmId -> Trie a -> OMap TableName a -trieToOMap rId t = OMap.fromList [(TableName rId k, v) | (k, v) <- toList t] +trieToOMap :: Trie a -> OMap TableName a +trieToOMap t = OMap.fromList [(tableName k, v) | (k, v) <- toList t] -sirToFLIR :: RealmId -> SIR.Realm -> FLIR.Realm -sirToFLIR rId r = +sirToFLIR :: SIR.Realm -> FLIR.Realm +sirToFLIR r = FLIR.Realm - { entities = trieToOMap rId $ fmap flattenEntity r.entities - , definitions = trieToOMap rId $ fmap flattenDefinition r.definitions - , rules = trieToOMap rId $ fmap flattenRule r.rules + { entities = trieToOMap $ fmap flattenEntity r.entities + , definitions = trieToOMap $ fmap flattenDefinition r.definitions + , rules = trieToOMap $ fmap flattenRule r.rules } diff --git a/packages/coln-compiler/src/Coln/FLIR/Value.hs b/packages/coln-compiler/src/Coln/FLIR/Value.hs index 1d2da5be..01524ff2 100644 --- a/packages/coln-compiler/src/Coln/FLIR/Value.hs +++ b/packages/coln-compiler/src/Coln/FLIR/Value.hs @@ -1,3 +1,4 @@ +{-# OPTIONS_GHC -Wno-orphans #-} module Coln.FLIR.Value where import Coln.Common @@ -17,7 +18,7 @@ import FNotation qualified as N import FNotation.Kinds qualified as K import GHC.Generics -type ColName = Path +type ColName = TableName type ColType = SIR.ScalarType @@ -98,8 +99,12 @@ aeOptions = , AE.constructorTagModifier = \x -> fmap toLower (take 1 x) ++ (drop 1 x) } -pathMapEncoding :: (SIR.PathLike k) => (a -> AE.Encoding) -> OMap k a -> AE.Encoding -pathMapEncoding f = AE.list (\(k, v) -> AE.pairs $ AE.pair "path" (SIR.encPath k) <> AE.pair "value" (f v)) . OMap.assocs +pathMapEncoding :: (a -> AE.Encoding) -> OMap TableName a -> AE.Encoding +pathMapEncoding f = AE.list (\(k, v) -> AE.pairs $ AE.pair "path" (AE.toEncoding k) <> AE.pair "value" (f v)) . OMap.assocs + +instance AE.ToJSON TableName where + toJSON = panic "aesons behaving badly" + toEncoding = AE.toEncoding . (.name) instance AE.ToJSON Materialization where toEncoding = AE.genericToEncoding aeOptions{AE.allNullaryToStringTag = True} @@ -112,7 +117,7 @@ instance AE.ToJSON EntityVariant where toEncoding = \case Table -> SIR.taggedEncoding "table" $ mempty View m -> SIR.taggedEncoding "view" $ AE.pair "materialization" $ AE.toEncoding m - Index m cs -> SIR.taggedEncoding "index" $ AE.pair "method" (AE.toEncoding m) <> AE.pair "columns" (AE.list SIR.encPath cs) + Index m cs -> SIR.taggedEncoding "index" $ AE.pair "method" (AE.toEncoding m) <> AE.pair "columns" (AE.list AE.toEncoding cs) instance AE.ToJSON Entity where toJSON = panic "aesons behaving badly" @@ -120,7 +125,7 @@ instance AE.ToJSON Entity where AE.pairs $ mconcat [ AE.pair "entityVariant" $ AE.toEncoding e.entityVariant - , AE.pair "columns" $ AE.list (\(k, v) -> AE.pairs $ AE.pair "path" (SIR.encPath k) <> AE.pair "type" (AE.toEncoding v)) e.columns + , AE.pair "columns" $ AE.list (\(k, v) -> AE.pairs $ AE.pair "path" (AE.toEncoding k) <> AE.pair "type" (AE.toEncoding v)) e.columns , AE.pair "primaryKey" $ fromMaybe AE.null_ $ fmap (AE.list AE.toEncoding) e.primaryKey ] @@ -138,7 +143,7 @@ instance AE.ToJSON Atom where toEncoding a = AE.pairs $ mconcat - [ AE.pair "entity" $ SIR.encPath a.entity + [ AE.pair "entity" $ AE.toEncoding a.entity , AE.pair "rowId" $ AE.toEncoding a.rowId , AE.pair "values" $ AE.list (\(i, t) -> AE.pairs $ mconcat [ AE.pair "column" (AE.toEncoding i), AE.pair "term" (AE.toEncoding t) ]) a.values ] @@ -153,9 +158,9 @@ instance AE.ToJSON Definition where toEncoding r = AE.pairs $ mconcat - [ AE.pair "vars" $ AE.list (AE.list id . (\(x, y) -> [x, y]) . (SIR.encPath *** AE.toEncoding)) $ r.vars + [ AE.pair "vars" $ AE.list (AE.list id . (\(x, y) -> [x, y]) . (AE.toEncoding *** AE.toEncoding)) $ r.vars , AE.pair "antecedents" $ AE.toEncoding r.antecedents - , AE.pair "definand" $ SIR.encPath r.definand + , AE.pair "definand" $ AE.toEncoding r.definand , AE.pair "arguments" $ AE.toEncoding r.args ] @@ -165,7 +170,7 @@ instance AE.ToJSON Rule where AE.pairs $ mconcat [ AE.pair "ruleVariant" $ AE.toEncoding r.ruleVariant - , AE.pair "vars" $ AE.list (AE.list id . (\(x, y) -> [x, y]) . (SIR.encPath *** AE.toEncoding)) $ r.vars + , AE.pair "vars" $ AE.list (AE.list id . (\(x, y) -> [x, y]) . (AE.toEncoding *** AE.toEncoding)) $ r.vars , AE.pair "antecedents" $ AE.toEncoding r.antecedents , AE.pair "consequents" $ AE.toEncoding r.consequents ] @@ -188,18 +193,8 @@ ruleVariantDeclKeyword e = Name [] $ case e of SIR.Enforced -> "enforced" SIR.Monitored -> "monitored" -toNotationColName :: ColName -> N.Ntn0 -toNotationColName BwdNil = N.Tuple [] () -- Shouldn't happen -toNotationColName (BwdNil :> x) = N.Field x () -toNotationColName (p :> x) = N.Juxt (toNotationColName p) (N.Field x ()) - -instance ToNotationTop Path where - toNotationTop BwdNil = N.Tuple [] () -- Shouldn't happen - toNotationTop (BwdNil :> x) = N.Ident x () - toNotationTop (p :> x) = N.Juxt (toNotationTop p) (N.Field x ()) - instance ToNotationTop TableName where - toNotationTop tn = foldl (\n p -> N.Juxt n (N.Field p ())) (N.Ident "ℜ" ()) tn.path + toNotationTop tn = N.Raw tn.name () instance ToNotationTop ColType where toNotationTop = \case @@ -207,7 +202,7 @@ instance ToNotationTop ColType where SIR.BuiltinTy bt -> N.Keyword (fromString $ show bt) () instance ToNotationTop (ColName, ColType) where - toNotationTop (n, t) = N.Infix (toNotationColName n) (N.Keyword ":" ()) (toNotationTop t) + toNotationTop (n, t) = N.Infix (toNotationTop n) (N.Keyword ":" ()) (toNotationTop t) instance ToNotationTop (TableName, Entity) where toNotationTop (tn, e) = do @@ -215,7 +210,7 @@ instance ToNotationTop (TableName, Entity) where let cols = N.Tuple (map toNotationTop e.columns) () let colsWKey = case e.primaryKey of Nothing -> cols - Just primaryKey -> N.Infix cols (N.Keyword "primarykey" ()) (N.Tuple (map toNotationColName $ map (fst . (e.columns !!)) primaryKey) ()) + Just primaryKey -> N.Infix cols (N.Keyword "primarykey" ()) (N.Tuple (map toNotationTop $ map (fst . (e.columns !!)) primaryKey) ()) N.Decl keyword (N.Infix (toNotationTop tn) (N.Keyword ":=" ()) colsWKey) () instance ToNotationTop Literal where @@ -234,7 +229,7 @@ toNotationAtom columnNames cs a = do let cols = case OMap.lookup a.entity columnNames of Just cols -> cols Nothing -> panic $ show a.entity ++ " not found" - let field (i, t) = N.Infix (toNotationColName (cols !! i)) (N.Keyword "↦" ()) (toNotationTerm cs t) + let field (i, t) = N.Infix (toNotationTop (cols !! i)) (N.Keyword "↦" ()) (toNotationTerm cs t) let body = N.Juxt entity $ N.Tuple (map field a.values) () case a.rowId of Nothing -> body diff --git a/packages/coln-compiler/src/Coln/MIR/Layout.hs b/packages/coln-compiler/src/Coln/MIR/Layout.hs index d01c990a..86db9225 100644 --- a/packages/coln-compiler/src/Coln/MIR/Layout.hs +++ b/packages/coln-compiler/src/Coln/MIR/Layout.hs @@ -32,10 +32,9 @@ data Scope = Scope , bound :: Bwd (V.El N Set) , locals :: V.Locals , usedNames :: Set.Set Name - , realm :: RealmId } -emptyScope :: RealmId -> Scope +emptyScope :: Scope emptyScope = Scope 0 BwdNil BwdNil BwdNil BwdNil Set.empty bind :: Scope -> Name -> V.Ty N Set -> (V.El N Set, Scope) @@ -59,10 +58,10 @@ layout :: Path -> Providence -> Scope -> V.Ty N Theory -> (Trie Generator, M.El layout p pr sc = \case V.LiftTy LSetTheory a -> do let gt = Leaf (Generator pr sc.names sc.ctx (GenLift a)) - (gt, M.liftEl $ M.lookup (TableName sc.realm p) (args sc) (M.fromV sc.len a)) + (gt, M.liftEl $ M.lookup (tableName p) (args sc) (M.fromV sc.len a)) V.U (inferSetCodes -> u) -> do let gt = Leaf (Generator pr sc.names sc.ctx (GenU u)) - (gt, M.primCode u (TableName sc.realm p) (args sc)) + (gt, M.primCode u (tableName p) (args sc)) V.Function ft -> case ft.variant.mlevel of SSetTheory -> do let x = argName sc.usedNames ft.cod @@ -79,8 +78,8 @@ layout p pr sc = \case let gt = Node $ Dict rt.fieldTypes.head (Vector.fromList gts) (gt, M.cons (Dict rt.fieldTypes.head (Vector.fromList ms))) -layoutTop :: RealmId -> V.Ty N Theory -> (Trie Generator, M.El N Theory) -layoutTop x = layout (BwdNil :> "root") Profane (emptyScope x) +layoutTop :: V.Ty N Theory -> (Trie Generator, M.El N Theory) +layoutTop = layout (BwdNil :> "root") Profane emptyScope asNominative :: V.El D Set -> V.El N Set asNominative = \case diff --git a/packages/coln-compiler/src/Coln/MIR/Top.hs b/packages/coln-compiler/src/Coln/MIR/Top.hs index e0270c38..c0c0548a 100644 --- a/packages/coln-compiler/src/Coln/MIR/Top.hs +++ b/packages/coln-compiler/src/Coln/MIR/Top.hs @@ -45,15 +45,15 @@ interpGlobals g = foldl go OMap.empty $ OMap.assocs g.definitions go :: V.Globals -> (Name, Core.Definition Global) -> V.Globals go acc (x, def) = acc OMap.>| (x, interp' acc x def) -coreToMIR :: V.Globals -> RealmId -> Core.Realm -> MIR.Realm -coreToMIR g rId r = do +coreToMIR :: V.Globals -> Core.Realm -> MIR.Realm +coreToMIR g r = do let rTy = interpAt STheory g BwdNil r.rootType.stx - let (rootgens, rootbody) = layoutTop rId rTy + let (rootgens, rootbody) = layoutTop rTy let go :: (Int, V.Locals) -> (Name, Core.Definition Local) -> ((Int, V.Locals), (Name, (Trie Generator, RealmDefinition))) go (n, ls) (x, def) = do let ty = interpAt STheory g ls $ readb n def.ty let bodyD = interpAt STheory g ls def.body.stx - let (gens, body) = declareEvaluation (BwdNil :> "init" :> x) (emptyScope rId) bodyD + let (gens, body) = declareEvaluation (BwdNil :> "init" :> x) emptyScope bodyD let l' = Pair STheory body.val let def' = RealmDefinition diff --git a/packages/coln-compiler/src/Coln/SIR/Cache.hs b/packages/coln-compiler/src/Coln/SIR/Cache.hs index 9d929099..000aeca3 100644 --- a/packages/coln-compiler/src/Coln/SIR/Cache.hs +++ b/packages/coln-compiler/src/Coln/SIR/Cache.hs @@ -19,18 +19,16 @@ data Scope = Scope , names :: Bwd Name , bound :: Bwd (V.El N Set) , used :: Set.Set Name - , realm :: RealmId } -emptyScope :: RealmId -> Scope -emptyScope rId = +emptyScope :: Scope +emptyScope = Scope { len = 0 , ctx = BwdNil , names = BwdNil , bound = BwdNil , used = Set.empty - , realm = rId } bind :: Scope -> Maybe Name -> V.Ty N Set -> (Name, V.El N Set, Scope) @@ -68,7 +66,7 @@ cache x p sc v = do let bound = toList (sc.bound :> V.local (FId sc.len)) let boundStx = separate (sc.len + 1) <$> bound let ent = Entity (View Materialized) (second (.shape) <$> cols) (Just [0 .. sc.len]) - let tn = TableName sc.realm p + let tn = tableName p let def = Definition cols tn boundStx let elt = S.SelectLast u tn (separate sc.len <$> toList sc.bound) (shapeOf a) (Leaf ent, Node (fromList [("definition", Leaf def)]), elt) @@ -89,5 +87,5 @@ cache x p sc v = do , S.Cons (Dict fields.head (fromList fields')) ) -cacheTop :: RealmId -> Name -> V.RealmDefinition -> (Trie Entity, Trie Definition, S.El Theory) -cacheTop rId x def = cache x (BwdNil :> "view" :> x) (emptyScope rId) def.body.val +cacheTop :: Name -> V.RealmDefinition -> (Trie Entity, Trie Definition, S.El Theory) +cacheTop x def = cache x (BwdNil :> "view" :> x) emptyScope def.body.val diff --git a/packages/coln-compiler/src/Coln/SIR/Separate.hs b/packages/coln-compiler/src/Coln/SIR/Separate.hs index e93fc917..c59d538b 100644 --- a/packages/coln-compiler/src/Coln/SIR/Separate.hs +++ b/packages/coln-compiler/src/Coln/SIR/Separate.hs @@ -118,10 +118,7 @@ separateGenerator tn gen = do let rule = Rule Monitored Antecedent cols S.trueProp codProp (Nothing, Nothing, Just $ Leaf rule) HSet -> do - let tableNameLast = case tn.path of - (_ :> last) -> last - BwdNil -> tn.realm - let resultName = freshenFor names tableNameLast + let resultName = freshNameFor names let resultQ = separate argNum a case gen.providence of diff --git a/packages/coln-compiler/src/Coln/SIR/Syntax.hs b/packages/coln-compiler/src/Coln/SIR/Syntax.hs index df1cd04d..2a2c4eb5 100644 --- a/packages/coln-compiler/src/Coln/SIR/Syntax.hs +++ b/packages/coln-compiler/src/Coln/SIR/Syntax.hs @@ -67,24 +67,11 @@ aeOptions = , AE.constructorTagModifier = \x -> fmap toLower (take 1 x) ++ (drop 1 x) } -class PathLike a where - namesOf :: a -> [Name] - -encName :: Name -> AE.Encoding -encName n = AE.list AE.toEncoding $ n.init ++ [n.last] - -encPath :: (PathLike a) => a -> AE.Encoding -encPath = AE.list encName . namesOf - -instance PathLike Path where namesOf = toList - -instance PathLike TableName where namesOf tn = tn.realm : namesOf tn.path - taggedEncoding :: Text -> AE.Series -> AE.Encoding taggedEncoding t v = AE.pairs $ AE.pair "tag" (AE.toEncoding t) <> v instance AE.ToJSON ScalarType where toJSON = panic "aesons behaving badly" toEncoding = \case - RowId e -> taggedEncoding "rowId" $ AE.pair "path" $ encPath e + RowId e -> taggedEncoding "rowId" $ AE.pair "path" $ AE.toEncoding e.name BuiltinTy bt -> taggedEncoding "builtin" $ AE.pair "type" $ AE.genericToEncoding aeOptions bt diff --git a/packages/coln-compiler/src/Coln/SIR/Top.hs b/packages/coln-compiler/src/Coln/SIR/Top.hs index d5ffafd7..d08d95be 100644 --- a/packages/coln-compiler/src/Coln/SIR/Top.hs +++ b/packages/coln-compiler/src/Coln/SIR/Top.hs @@ -47,11 +47,11 @@ fromNode Nothing = [] fromNode (Just Leaf{}) = panic "leaf at top of generator trie" fromNode (Just (Node d)) = toList d -mirToSIR :: RealmId -> MIR.Realm -> SIR.Realm -mirToSIR rId r = do - let (_, _, root) = cache "root" (BwdNil :> "root") (emptyScope rId) r.root - let (rootE, rootD, rootR) = aggregate3 (\p -> separateGenerator (TableName rId p)) BwdNil r.generators - let (names, cached) = unzip $ map (fst &&& uncurry (cacheTop rId)) $ OMap.assocs r.realmDefinitions +mirToSIR :: MIR.Realm -> SIR.Realm +mirToSIR r = do + let (_, _, root) = cache "root" (BwdNil :> "root") emptyScope r.root + let (rootE, rootD, rootR) = aggregate3 (\p -> separateGenerator (tableName p)) BwdNil r.generators + let (names, cached) = unzip $ map (fst &&& uncurry cacheTop) $ OMap.assocs r.realmDefinitions let (cachedE, cachedD, _) = unzip3 cached let viewE = Node $ fromList [(x, y) | (x, Just y) <- zip names (map cleanTrie cachedE)] let viewD = Node $ fromList [(x, y) | (x, Just y) <- zip names (map cleanTrie cachedD)] diff --git a/packages/coln-compiler/src/Coln/Top.hs b/packages/coln-compiler/src/Coln/Top.hs index 7657fa8c..cc62440f 100644 --- a/packages/coln-compiler/src/Coln/Top.hs +++ b/packages/coln-compiler/src/Coln/Top.hs @@ -46,8 +46,8 @@ loadRealms fp = do (rep, g) <- loadFile fp let realmsCore = OMap.assocs g.realms let globalsMIR = interpGlobals g - let realmsMIR = [(rId, coreToMIR globalsMIR rId r) | (rId, r) <- realmsCore] - let realmsSIR = [(rId, mirToSIR rId r) | (rId, r) <- realmsMIR] + let realmsMIR = [(rId, coreToMIR globalsMIR r) | (rId, r) <- realmsCore] + let realmsSIR = [(rId, mirToSIR r) | (rId, r) <- realmsMIR] pure (rep, OMap.fromList realmsSIR) compile :: FilePath -> T.Text -> (Reporter ColnCode, IO Globals) @@ -59,7 +59,7 @@ compile fp contents = do writeFLIR :: FilePath -> Reporter ColnCode -> OMap Name SIR.Realm -> IO () writeFLIR fp _ realms = for_ (OMap.assocs realms) $ \(rId, r) -> do - let flir = sirToFLIR rId r + let flir = sirToFLIR r let fn = fp mangleToString rId <> ".json" AE.encodeFile fn flir let pn = fp mangleToString rId <> ".pretty" diff --git a/packages/coln-compiler/test/golden/graph.coln b/packages/coln-compiler/test/golden/graph.coln index db0ae95d..617e5950 100644 --- a/packages/coln-compiler/test/golden/graph.coln +++ b/packages/coln-compiler/test/golden/graph.coln @@ -4,6 +4,16 @@ theory Graph := sig end realm GraphRealm @ Graph + def outgoing-edges (v : root.V) : Set := sig + into : root.V + has-edge : root.E v into + end + + def incoming-edges (v : root.V) : Set := sig + outof : root.V + has-edge : root.E outof v + end + def free-edge : Set := sig v0 : root.V v1 : root.V diff --git a/packages/coln-compiler/typescript-model/graph.ts b/packages/coln-compiler/typescript-model/graph.ts index f056a830..d2d34c91 100644 --- a/packages/coln-compiler/typescript-model/graph.ts +++ b/packages/coln-compiler/typescript-model/graph.ts @@ -10,10 +10,24 @@ export class GraphRealm { edge: (src: runtime.RowId<"root.vertex">) => (tgt: runtime.RowId<"root.vertex">) => runtime.MutableSet> } + incoming_edges: (v: runtime.RowId<"root.vertex">) => runtime.Set<{ from: runtime.RowId<"root.vertex">, edge: runtime.RowId<"root.edge"> }> + constructor(store: runtime.Store) { this.root = { - vertex: new runtime.BoundBaseTable(store, [["root"], ["vertex"]], []), + vertex: todo(), edge: todo() }; + this.incoming_edges = (v: runtime.RowId<"root.vertex">) => { + return new View(store, { table_name: "incoming_edges", row_id: null, values: [v] }, [1,2], (ts) => { return { from: ts[0], edge: ts[1] } }) + } } } + +const g = new GraphRealm(todo()) + +const v0 = g.root.vertex.add() +const e0 = g.root.edge(v0)(v0).add() + +const es = g.incoming_edges(v0).values() + +g.root.edge(es[0].from) diff --git a/packages/coln-compiler/typescript-model/runtime/flatten.ts b/packages/coln-compiler/typescript-model/runtime/flatten.ts index 2f52298a..29b4ae2b 100644 --- a/packages/coln-compiler/typescript-model/runtime/flatten.ts +++ b/packages/coln-compiler/typescript-model/runtime/flatten.ts @@ -1,5 +1,6 @@ import { WireTuple } from "./store"; -export class Adaptor { - constructor(public flatten: (value: T) => WireTuple, public reconstruct: (tuple: WireTuple) => T) {} +export interface Adaptor { + flatten: (value: T) => WireTuple, + reconstruct: (tuple: WireTuple) => T } diff --git a/packages/coln-compiler/typescript-model/runtime/set.ts b/packages/coln-compiler/typescript-model/runtime/set.ts index 368585d6..38570294 100644 --- a/packages/coln-compiler/typescript-model/runtime/set.ts +++ b/packages/coln-compiler/typescript-model/runtime/set.ts @@ -1,6 +1,7 @@ import { Store, WireTuple } from "./store.js"; -import { WhereClause } from "./types.js" +import { Path, WhereClause, WireRowId } from "./types.js" import { Adaptor } from "./flatten.js" +import { RowId } from "./row_id.js"; export interface Set { values(): T[] @@ -15,31 +16,31 @@ export interface MutableSet extends Set { add(): T } -export class BoundBaseTable implements MutableSet { - constructor(private store: Store) {} +export class BaseTableSet

implements MutableSet> { + constructor(private store: Store, private table_name: Path, private bound: WireTuple) {} - values(): T[] { - return todo() + values(): RowId

[] { + return this.store.all_row_id({ table_name: this.table_name, row_id: null, values: this.bound }).map((i: WireRowId) => {return new RowId()}) } - contains(v: T): boolean { + contains(v: RowId

): boolean { return todo() } - add(): T { + add(): RowId

{ return todo() } } -export class View { - constructor( - private store: Store, - private table_name: WhereClause, - private params: WireTuple, - private adapter: Adaptor - ) {} +export class ViewTableSet implements Set { + constructor(private store: Store, private table_name: Path, private bound: WireTuple, private select: [number], private adaptor: Adaptor) {} + + values(): T[] { + return this.store.all_proj({ table_name: this.table_name, row_id: null, values: this.bound }, this.select).map(this.adaptor.reconstruct) + } - // values(): T[] { - // return this.store.all(this.where, this.select).map(this.reconstruct) - // } + contains(v: T): boolean { + return this.store.exists({ table_name: this.table_name, row_id: null, values: [...this.bound, ...this.adaptor.flatten(v)] }) + } } + diff --git a/packages/coln-compiler/typescript-model/runtime/store.ts b/packages/coln-compiler/typescript-model/runtime/store.ts index f40d0447..1bf4c566 100644 --- a/packages/coln-compiler/typescript-model/runtime/store.ts +++ b/packages/coln-compiler/typescript-model/runtime/store.ts @@ -1,16 +1,20 @@ -import {WhereClause, WireRowId, Value, Path, CommitHash} from "./types.js" +import {WhereClause, TxnWireRowId, WireRowId, Value, Path, CommitHash} from "./types.js" export type WireValue = Value +export type TxnWireValue = Value export type WireTuple = WireValue[] +export type TxnWireTuple = TxnWireValue[] export interface Store { commit(): CommitHash abort(): null - all(query: WhereClause, select: [number]): [WireTuple] - one(query: WhereClause, select: [number]): WireTuple + all_proj(query: WhereClause, select: [number]): [WireTuple] + all_row_id(query: WhereClause): [WireRowId] + one_proj(query: WhereClause, select: [number]): WireTuple + // don't need one_row_id exists(query: WhereClause): boolean - add(table_name: Path, values: WireTuple): WireRowId + add(table_name: Path, values: TxnWireTuple): WireRowId } diff --git a/packages/coln-compiler/typescript-model/runtime/types.ts b/packages/coln-compiler/typescript-model/runtime/types.ts index 7d978ec1..2c05d48c 100644 --- a/packages/coln-compiler/typescript-model/runtime/types.ts +++ b/packages/coln-compiler/typescript-model/runtime/types.ts @@ -11,7 +11,11 @@ export type TxnWireRowId = { type: "Existing"; value: WireRowId } | { type: "Pen export type Value = I | number | string; -export type WhereClause = { type: "PrimaryKey"; values: Value[] } | { type: "ExceptRowId"; values: Value[] } | { type: "Generic"; values_at: ([number, Value])[] }; +export type WhereClause = { + table_name: Path, + row_id: WireRowId | null, + values: Value[], +}; /** * The unique id that identifies each row in a table. diff --git a/packages/coln-flir-rs/src/ir/mod.rs b/packages/coln-flir-rs/src/ir/mod.rs index 5c184ed5..95acde59 100644 --- a/packages/coln-flir-rs/src/ir/mod.rs +++ b/packages/coln-flir-rs/src/ir/mod.rs @@ -2,20 +2,48 @@ // // SPDX-License-Identifier: Apache-2.0 OR MIT -pub mod path; - use serde::de::Error as DeError; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use specta::Type; +use std::fmt; -// A QName is a vec of string, potentially separated by a forward slash / -pub type QName = Vec; - -// For example a G.V would become [["G"], ["V"]], this is at a higher level than -// QName because V would be a query inside a theory G #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Type)] #[serde(transparent)] -pub struct Path(pub Vec); +pub struct Path(pub String); + +impl Path { + pub fn from>(value: S) -> Self { + Path(value.into()) + } + + pub fn append>(&self, segment: S) -> Self { + Path(format!("{}.{}", &self.0, segment.as_ref())) + } +} + +impl From for String { + fn from(value: Path) -> Self { + value.0 + } +} + +impl From<&str> for Path { + fn from(value: &str) -> Self { + Path(value.into()) + } +} + +impl AsRef for Path { + fn as_ref<'a>(&'a self) -> &'a str { + self.0.as_ref() + } +} + +impl fmt::Display for Path { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} /// A column name is given by a [`Path`]. pub type ColName = Path; diff --git a/packages/coln-flir-rs/src/ir/path.rs b/packages/coln-flir-rs/src/ir/path.rs deleted file mode 100644 index 9347a6e0..00000000 --- a/packages/coln-flir-rs/src/ir/path.rs +++ /dev/null @@ -1,192 +0,0 @@ -// SPDX-FileCopyrightText: 2026 Coln contributors -// -// SPDX-License-Identifier: Apache-2.0 OR MIT - -use std::{ - convert::Infallible, - fmt::{self, Display}, - ops::Deref, - str::FromStr, -}; - -use super::{Path, QName}; - -impl Deref for Path { - type Target = Vec; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Path { - pub fn append(mut self, name: &str) -> Self { - self.0.push(vec![name.to_string()]); - self - } -} - -impl From for String { - fn from(value: Path) -> Self { - value.to_string() - } -} - -impl From<&Path> for String { - fn from(value: &Path) -> Self { - value.to_string() - } -} - -impl Display for Path { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (i, qname) in self.0.iter().enumerate() { - if i > 0 { - write!(f, ".")?; - } - - for (j, part) in qname.iter().enumerate() { - if j > 0 { - write!(f, "/")?; - } - write!(f, "{part}")?; - } - } - - Ok(()) - } -} - -/// Dotted textual form: each `.` separates one [`QName`]; within each dot segment, `/` -/// separates parts of that [`QName`] (e.g. `"G.V"` → `[["G"], ["V"]]`, `"G.A/B"` → -/// `[["G"], ["A", "B"]]`). Dot segments and `/` parts are trimmed; empty pieces are -/// skipped. An empty or whitespace-only string yields an empty path. -/// -/// Use [`Path::from`] on `&str` / [`String`], or [`str::parse`]. -/// -/// This function does not fail, as we do not really have a strict notion of what -/// is allowed not allowed in the string form of the path anyway -fn parse_path_from_str(s: &str) -> Path { - Path( - s.split('.') - .map(str::trim) - .filter(|seg| !seg.is_empty()) - .filter_map(|seg| { - let q = qname_from_slash_segment(seg); - (!q.is_empty()).then_some(q) - }) - .collect(), - ) -} - -impl From<&str> for Path { - fn from(s: &str) -> Self { - parse_path_from_str(s) - } -} - -impl From for Path { - fn from(s: String) -> Self { - Self::from(s.as_str()) - } -} - -impl FromStr for Path { - type Err = Infallible; - - fn from_str(s: &str) -> Result { - Ok(parse_path_from_str(s)) - } -} - -fn qname_from_slash_segment(seg: &str) -> QName { - seg.split('/') - .map(str::trim) - .filter(|part| !part.is_empty()) - .map(|part| part.to_string()) - .collect() -} - -#[cfg(test)] -mod path_parse_tests { - use super::*; - - #[test] - fn g_dot_v() { - assert_eq!( - Path::from("G.V"), - Path(vec![vec!["G".to_string()], vec!["V".to_string()]]) - ); - } - - #[test] - fn triple_segment() { - assert_eq!( - Path::from("Hom.E.foreignKeys"), - Path(vec![ - vec!["Hom".to_string()], - vec!["E".to_string()], - vec!["foreignKeys".to_string()], - ]) - ); - } - - #[test] - fn dot_separated_path_slash_separated_qname() { - assert_eq!( - Path::from("G.A/B"), - Path(vec![ - vec!["G".to_string()], - vec!["A".to_string(), "B".to_string()] - ]) - ); - } - - #[test] - fn slash_only_in_one_segment() { - assert_eq!( - Path::from("Hom.E/D.foreignKeys"), - Path(vec![ - vec!["Hom".to_string()], - vec!["E".to_string(), "D".to_string()], - vec!["foreignKeys".to_string()], - ]) - ); - } - - #[test] - fn qname_with_slashes_no_dots() { - assert_eq!( - Path::from("A/B/C"), - Path(vec![vec![ - "A".to_string(), - "B".to_string(), - "C".to_string() - ]]) - ); - } - - #[test] - fn from_string() { - assert_eq!(Path::from("G.V".to_string()), Path::from("G.V")); - } - - #[test] - fn from_str_parse() { - let p: Path = "G.V".parse().unwrap(); - assert_eq!(p, Path::from("G.V")); - } - - #[test] - fn display_round_trips_normalized_path() { - assert_eq!( - Path::from(" Hom . E / D . foreignKeys ").to_string(), - "Hom.E/D.foreignKeys" - ); - } - - #[test] - fn display_empty_path() { - assert_eq!(Path(vec![]).to_string(), ""); - } -} diff --git a/packages/coln-flir-rs/tests/data/GraphRealm.json b/packages/coln-flir-rs/tests/data/GraphRealm.json index 492596b7..8531170e 100644 --- a/packages/coln-flir-rs/tests/data/GraphRealm.json +++ b/packages/coln-flir-rs/tests/data/GraphRealm.json @@ -1,103 +1 @@ -{ - "entities": [ - { - "path": [["GraphRealm"], ["root"], ["V"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [], - "primaryKey": null - } - }, - { - "path": [["GraphRealm"], ["root"], ["E"]], - "value": { - "entityVariant": { "tag": "table" }, - "columns": [ - { - "path": [["a"]], - "type": { - "tag": "rowId", - "path": [["GraphRealm"], ["root"], ["V"]] - } - }, - { - "path": [["b"]], - "type": { - "tag": "rowId", - "path": [["GraphRealm"], ["root"], ["V"]] - } - } - ], - "primaryKey": null - } - } - ], - "definitions": [], - "rules": [ - { - "path": [["GraphRealm"], ["root"], ["V"], ["foreignKey"]], - "value": { - "ruleVariant": "enforced", - "vars": [], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphRealm"], ["root"], ["V"]], - "rowId": null, - "values": [] - } - } - ], - "consequents": [] - } - }, - { - "path": [["GraphRealm"], ["root"], ["E"], ["foreignKey"]], - "value": { - "ruleVariant": "enforced", - "vars": [ - [ - [["a"]], - { "tag": "rowId", "path": [["GraphRealm"], ["root"], ["V"]] } - ], - [ - [["b"]], - { "tag": "rowId", "path": [["GraphRealm"], ["root"], ["V"]] } - ] - ], - "antecedents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphRealm"], ["root"], ["E"]], - "rowId": null, - "values": [ - { "column": 0, "term": { "tag": "var", "index": 0 } }, - { "column": 1, "term": { "tag": "var", "index": 1 } } - ] - } - } - ], - "consequents": [ - { - "tag": "atom", - "atom": { - "entity": [["GraphRealm"], ["root"], ["V"]], - "rowId": { "tag": "var", "index": 0 }, - "values": [] - } - }, - { - "tag": "atom", - "atom": { - "entity": [["GraphRealm"], ["root"], ["V"]], - "rowId": { "tag": "var", "index": 1 }, - "values": [] - } - } - ] - } - } - ] -} +{"entities":[{"path":"root.V","value":{"entityVariant":{"tag":"table"},"columns":[],"primaryKey":null}},{"path":"root.E","value":{"entityVariant":{"tag":"table"},"columns":[{"path":"a","type":{"tag":"rowId","path":"root.V"}},{"path":"b","type":{"tag":"rowId","path":"root.V"}}],"primaryKey":null}},{"path":"view.outgoing-edges","value":{"entityVariant":{"tag":"view","materialization":"materialized"},"columns":[{"path":"v","type":{"tag":"rowId","path":"root.V"}},{"path":"outgoing-edges.into","type":{"tag":"rowId","path":"root.V"}},{"path":"outgoing-edges.has-edge","type":{"tag":"rowId","path":"root.E"}}],"primaryKey":[0,1,2]}},{"path":"view.incoming-edges","value":{"entityVariant":{"tag":"view","materialization":"materialized"},"columns":[{"path":"v","type":{"tag":"rowId","path":"root.V"}},{"path":"incoming-edges.outof","type":{"tag":"rowId","path":"root.V"}},{"path":"incoming-edges.has-edge","type":{"tag":"rowId","path":"root.E"}}],"primaryKey":[0,1,2]}},{"path":"view.free-edge","value":{"entityVariant":{"tag":"view","materialization":"materialized"},"columns":[{"path":"free-edge.v0","type":{"tag":"rowId","path":"root.V"}},{"path":"free-edge.v1","type":{"tag":"rowId","path":"root.V"}},{"path":"free-edge.e","type":{"tag":"rowId","path":"root.E"}}],"primaryKey":[0,1,2]}},{"path":"view.free-edge-pair","value":{"entityVariant":{"tag":"view","materialization":"materialized"},"columns":[{"path":"free-edge-pair.e0.v0","type":{"tag":"rowId","path":"root.V"}},{"path":"free-edge-pair.e0.v1","type":{"tag":"rowId","path":"root.V"}},{"path":"free-edge-pair.e0.e","type":{"tag":"rowId","path":"root.E"}},{"path":"free-edge-pair.e1.v0","type":{"tag":"rowId","path":"root.V"}},{"path":"free-edge-pair.e1.v1","type":{"tag":"rowId","path":"root.V"}},{"path":"free-edge-pair.e1.e","type":{"tag":"rowId","path":"root.E"}}],"primaryKey":[0,1,2,3,4,5]}}],"definitions":[{"path":"view.outgoing-edges.definition","value":{"vars":[["v",{"tag":"rowId","path":"root.V"}],["outgoing-edges.into",{"tag":"rowId","path":"root.V"}],["outgoing-edges.has-edge",{"tag":"rowId","path":"root.E"}]],"antecedents":[{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":"root.E","rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}}],"definand":"view.outgoing-edges","arguments":[{"tag":"var","index":0},{"tag":"var","index":1},{"tag":"var","index":2}]}},{"path":"view.incoming-edges.definition","value":{"vars":[["v",{"tag":"rowId","path":"root.V"}],["incoming-edges.outof",{"tag":"rowId","path":"root.V"}],["incoming-edges.has-edge",{"tag":"rowId","path":"root.E"}]],"antecedents":[{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":"root.E","rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":1}},{"column":1,"term":{"tag":"var","index":0}}]}}],"definand":"view.incoming-edges","arguments":[{"tag":"var","index":0},{"tag":"var","index":1},{"tag":"var","index":2}]}},{"path":"view.free-edge.definition","value":{"vars":[["free-edge.v0",{"tag":"rowId","path":"root.V"}],["free-edge.v1",{"tag":"rowId","path":"root.V"}],["free-edge.e",{"tag":"rowId","path":"root.E"}]],"antecedents":[{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":"root.E","rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}}],"definand":"view.free-edge","arguments":[{"tag":"var","index":0},{"tag":"var","index":1},{"tag":"var","index":2}]}},{"path":"view.free-edge-pair.definition","value":{"vars":[["free-edge-pair.e0.v0",{"tag":"rowId","path":"root.V"}],["free-edge-pair.e0.v1",{"tag":"rowId","path":"root.V"}],["free-edge-pair.e0.e",{"tag":"rowId","path":"root.E"}],["free-edge-pair.e1.v0",{"tag":"rowId","path":"root.V"}],["free-edge-pair.e1.v1",{"tag":"rowId","path":"root.V"}],["free-edge-pair.e1.e",{"tag":"rowId","path":"root.E"}]],"antecedents":[{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":1},"values":[]}},{"tag":"atom","atom":{"entity":"root.E","rowId":{"tag":"var","index":2},"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}},{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":3},"values":[]}},{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":4},"values":[]}},{"tag":"atom","atom":{"entity":"root.E","rowId":{"tag":"var","index":5},"values":[{"column":0,"term":{"tag":"var","index":3}},{"column":1,"term":{"tag":"var","index":4}}]}}],"definand":"view.free-edge-pair","arguments":[{"tag":"var","index":0},{"tag":"var","index":1},{"tag":"var","index":2},{"tag":"var","index":3},{"tag":"var","index":4},{"tag":"var","index":5}]}}],"rules":[{"path":"root.V.foreignKey","value":{"ruleVariant":"enforced","vars":[],"antecedents":[{"tag":"atom","atom":{"entity":"root.V","rowId":null,"values":[]}}],"consequents":[]}},{"path":"root.E.foreignKey","value":{"ruleVariant":"enforced","vars":[["a",{"tag":"rowId","path":"root.V"}],["b",{"tag":"rowId","path":"root.V"}]],"antecedents":[{"tag":"atom","atom":{"entity":"root.E","rowId":null,"values":[{"column":0,"term":{"tag":"var","index":0}},{"column":1,"term":{"tag":"var","index":1}}]}}],"consequents":[{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":0},"values":[]}},{"tag":"atom","atom":{"entity":"root.V","rowId":{"tag":"var","index":1},"values":[]}}]}}]} \ No newline at end of file diff --git a/packages/coln-flir-rs/tests/data/GraphRealm.pretty b/packages/coln-flir-rs/tests/data/GraphRealm.pretty index e9386260..dd63974b 100644 --- a/packages/coln-flir-rs/tests/data/GraphRealm.pretty +++ b/packages/coln-flir-rs/tests/data/GraphRealm.pretty @@ -1,15 +1,83 @@ flatrealm entities - table ℜ.root.V := [] - table ℜ.root.E := [.a : ℜ.root.V, .b : ℜ.root.V] + table root.V := [] + table root.E := [a : root.V, b : root.V] + view view.outgoing-edges := [ + v : root.V, + outgoing-edges.into : root.V, + outgoing-edges.has-edge : root.E + ] primarykey [v, outgoing-edges.into, outgoing-edges.has-edge] + view view.incoming-edges := [ + v : root.V, + incoming-edges.outof : root.V, + incoming-edges.has-edge : root.E + ] primarykey [v, incoming-edges.outof, incoming-edges.has-edge] + view view.free-edge := [ + free-edge.v0 : root.V, + free-edge.v1 : root.V, + free-edge.e : root.E + ] primarykey [free-edge.v0, free-edge.v1, free-edge.e] + view view.free-edge-pair := [ + free-edge-pair.e0.v0 : root.V, + free-edge-pair.e0.v1 : root.V, + free-edge-pair.e0.e : root.E, + free-edge-pair.e1.v0 : root.V, + free-edge-pair.e1.v1 : root.V, + free-edge-pair.e1.e : root.E + ] primarykey [ + free-edge-pair.e0.v0, + free-edge-pair.e0.v1, + free-edge-pair.e0.e, + free-edge-pair.e1.v0, + free-edge-pair.e1.v1, + free-edge-pair.e1.e + ] end definitions + chased view.outgoing-edges.definition v outgoing-edges.into outgoing-edges.has-edge := v ∈ root.V [] ∧ outgoing-edges.into ∈ root.V [] ∧ outgoing-edges.has-edge ∈ root.E [ + a ↦ v, + b ↦ outgoing-edges.into + ] ⊢ view.outgoing-edges [ + v ↦ v, + outgoing-edges.into ↦ outgoing-edges.into, + outgoing-edges.has-edge ↦ outgoing-edges.has-edge + ] + chased view.incoming-edges.definition v incoming-edges.outof incoming-edges.has-edge := v ∈ root.V [] ∧ incoming-edges.outof ∈ root.V [] ∧ incoming-edges.has-edge ∈ root.E [ + a ↦ incoming-edges.outof, + b ↦ v + ] ⊢ view.incoming-edges [ + v ↦ v, + incoming-edges.outof ↦ incoming-edges.outof, + incoming-edges.has-edge ↦ incoming-edges.has-edge + ] + chased view.free-edge.definition free-edge.v0 free-edge.v1 free-edge.e := free-edge.v0 ∈ root.V [] ∧ free-edge.v1 ∈ root.V [] ∧ free-edge.e ∈ root.E [ + a ↦ free-edge.v0, + b ↦ free-edge.v1 + ] ⊢ view.free-edge [ + free-edge.v0 ↦ free-edge.v0, + free-edge.v1 ↦ free-edge.v1, + free-edge.e ↦ free-edge.e + ] + chased view.free-edge-pair.definition free-edge-pair.e0.v0 free-edge-pair.e0.v1 free-edge-pair.e0.e free-edge-pair.e1.v0 free-edge-pair.e1.v1 free-edge-pair.e1.e := free-edge-pair.e0.v0 ∈ root.V [] ∧ free-edge-pair.e0.v1 ∈ root.V [] ∧ free-edge-pair.e0.e ∈ root.E [ + a ↦ free-edge-pair.e0.v0, + b ↦ free-edge-pair.e0.v1 + ] ∧ free-edge-pair.e1.v0 ∈ root.V [] ∧ free-edge-pair.e1.v1 ∈ root.V [] ∧ free-edge-pair.e1.e ∈ root.E [ + a ↦ free-edge-pair.e1.v0, + b ↦ free-edge-pair.e1.v1 + ] ⊢ view.free-edge-pair [ + free-edge-pair.e0.v0 ↦ free-edge-pair.e0.v0, + free-edge-pair.e0.v1 ↦ free-edge-pair.e0.v1, + free-edge-pair.e0.e ↦ free-edge-pair.e0.e, + free-edge-pair.e1.v0 ↦ free-edge-pair.e1.v0, + free-edge-pair.e1.v1 ↦ free-edge-pair.e1.v1, + free-edge-pair.e1.e ↦ free-edge-pair.e1.e + ] end rules - enforced ℜ.root.V.foreignKey := ℜ.root.V [] ⊢ ⊤ - enforced ℜ.root.E.foreignKey a b := ℜ.root.E [ - .a ↦ a, - .b ↦ b - ] ⊢ a ∈ ℜ.root.V [] ∧ b ∈ ℜ.root.V [] + enforced root.V.foreignKey := root.V [] ⊢ ⊤ + enforced root.E.foreignKey a b := root.E [ + a ↦ a, + b ↦ b + ] ⊢ a ∈ root.V [] ∧ b ∈ root.V [] end end \ No newline at end of file diff --git a/packages/coln-query/src/api/query.rs b/packages/coln-query/src/api/query.rs index 13073730..a5aaf1ee 100644 --- a/packages/coln-query/src/api/query.rs +++ b/packages/coln-query/src/api/query.rs @@ -95,7 +95,7 @@ impl From<&BaseTableSchema> for TableSchema { let columns = value .query_cols() .iter() - .map(|col| Column::new(col.name(), *col.ty())) + .map(|col| Column::new(col.name().to_string(), *col.ty())) .collect(); let row_id_key = value .resolve_query_col_range(CompilerColIdx::for_row_id()) @@ -395,7 +395,7 @@ impl FlirProgram { })?; binder.conditions.push(Expr::from(BinaryExpr { operator: Operator::Equal, - left: Expr::from(VarExpr::new(column.name())), + left: Expr::from(VarExpr::new(column.name().as_ref())), right: Expr::from(LiteralExpr::from(Literal::from(lit))), })); } diff --git a/packages/coln-rpc/src/rust/api.rs b/packages/coln-rpc/src/rust/api.rs index 360f1a9a..f501b3c7 100644 --- a/packages/coln-rpc/src/rust/api.rs +++ b/packages/coln-rpc/src/rust/api.rs @@ -1,13 +1,12 @@ -use coln_flir_rs::ir; +use coln_flir_rs::ir::{self, Path}; use serde::{Deserialize, Serialize}; use specta::Type; // use coln_store::id_packer::IdPacker; -use coln_store::{table::{WireValue}, txn::TxnWireRowId}; +use coln_store::{table::{WireRowId, WireValue}}; #[derive(Type, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum WhereClause { - PrimaryKey { values: Vec }, - ExceptRowId { values: Vec }, - Generic { values_at: Vec<(u32, WireValue)> }, +pub struct WhereClause { + table_name: Path, + row_id: Option, + values: Vec // A prefix of column values } diff --git a/packages/coln-store/src/commit/wire/prim.rs b/packages/coln-store/src/commit/wire/prim.rs index 076c5696..63b63322 100644 --- a/packages/coln-store/src/commit/wire/prim.rs +++ b/packages/coln-store/src/commit/wire/prim.rs @@ -213,33 +213,16 @@ pub(crate) fn decode_prim_value( pub(crate) fn encode_path(path: &ir::Path) -> Vec { let mut out = Vec::new(); - commit_leb128::write_len(&mut out, path.0.len()); - for qname in &path.0 { - commit_leb128::write_len(&mut out, qname.len()); - for part in qname { - commit_leb128::write_len_prefixed_bytes(&mut out, part.as_bytes()); - } - } + commit_leb128::write_len_prefixed_bytes(&mut out, path.as_ref().as_bytes()); out } pub(crate) fn decode_path(data: &[u8], pos: &mut usize) -> Result { - let qname_count = commit_leb128::read_len(data, pos, "path name count")?; - let mut path = Vec::with_capacity(qname_count); - - for _ in 0..qname_count { - let part_count = commit_leb128::read_len(data, pos, "part count")?; - let mut qname = Vec::with_capacity(part_count); - for _ in 0..part_count { - let part_bytes = commit_leb128::read_len_prefixed_bytes(data, pos, "qname part")?; - let part = std::str::from_utf8(part_bytes) - .map_err(|_| CodecError::DataFormatError("path part invalid utf-8".into()))?; - qname.push(part.to_owned()) - } - path.push(qname); - } + let path_bytes = commit_leb128::read_len_prefixed_bytes(data, pos, "path")?; + let path = std::str::from_utf8(path_bytes) + .map_err(|_| CodecError::DataFormatError("path invalid utf-8".into()))?; - Ok(ir::Path(path)) + Ok(ir::Path(path.into())) } #[allow(dead_code)] diff --git a/packages/coln-store/src/repl/exe/sql.rs b/packages/coln-store/src/repl/exe/sql.rs index 4d3e3fe3..e0a7ed75 100644 --- a/packages/coln-store/src/repl/exe/sql.rs +++ b/packages/coln-store/src/repl/exe/sql.rs @@ -253,7 +253,7 @@ mod tests { let loaded = session.loaded.as_ref().expect("loaded session"); let table = loaded .store - .table_at(&"Person".parse().unwrap()) + .table_at(&"Person".into()) .expect("Person table"); assert_eq!(table.row_count(), 2); @@ -276,7 +276,7 @@ mod tests { let loaded = session.loaded.as_ref().expect("loaded session"); let dump = loaded .store - .table_at(&"Person".parse().unwrap()) + .table_at(&"Person".into()) .expect("Person table") .dump(); assert!(dump.contains("alice")); diff --git a/packages/coln-store/src/repl/mod.rs b/packages/coln-store/src/repl/mod.rs index bd6c020b..91361b3c 100644 --- a/packages/coln-store/src/repl/mod.rs +++ b/packages/coln-store/src/repl/mod.rs @@ -278,14 +278,7 @@ mod tests { assert!(message.contains(":0, #")); assert!(message.ends_with(":1]")); let loaded = session.loaded.as_ref().expect("loaded session"); - assert_eq!( - loaded - .store - .table_at(&"T".parse().unwrap()) - .unwrap() - .row_count(), - 2 - ); + assert_eq!(loaded.store.table_at(&"T".into()).unwrap().row_count(), 2); } #[test] @@ -338,7 +331,7 @@ mod tests { assert_eq!(message, "created table Person"); let loaded = session.loaded.as_ref().expect("sql store loaded"); - assert!(loaded.store.table_at(&"Person".parse().unwrap()).is_some()); + assert!(loaded.store.table_at(&"Person".into()).is_some()); assert_eq!(loaded.schema.table_count, 1); assert_eq!(loaded.schema.tables[0].path, "Person"); assert_eq!( @@ -410,7 +403,7 @@ mod tests { let loaded = session.loaded.as_ref().expect("loaded session"); let table = loaded .store - .table_at(&"Person".parse().unwrap()) + .table_at(&"Person".into()) .expect("Person table"); assert_eq!(table.row_count(), 2); // The fixture header order (age, name) differs from the schema order. @@ -422,17 +415,15 @@ mod tests { #[test] fn add_rejects_bad_entity_id() { let mut store = Store::new(); - let path: crate::ir::Path = "Ref".parse().unwrap(); + let path: crate::ir::Path = "Ref".into(); store .create_table( path, crate::ir::Schema { entity_variant: EntityVariant::Table, columns: vec![ColumnEntry { - path: "ref".parse().unwrap(), - col_type: ColType::RowId { - path: "T".parse().unwrap(), - }, + path: "ref".into(), + col_type: ColType::RowId { path: "T".into() }, }], primary_key: None, }, @@ -462,7 +453,7 @@ mod tests { let loaded = session.loaded.as_ref().expect("loaded session"); let table = loaded .store - .table_at(&"Person".parse().unwrap()) + .table_at(&"Person".into()) .expect("Person table"); assert_eq!(table.row_count(), 2); } @@ -497,14 +488,7 @@ mod tests { .expect("spanned batch"); let loaded = session.loaded.as_ref().expect("loaded session"); - assert_eq!( - loaded - .store - .table_at(&"T".parse().unwrap()) - .unwrap() - .row_count(), - 1 - ); + assert_eq!(loaded.store.table_at(&"T".into()).unwrap().row_count(), 1); } #[test] @@ -542,7 +526,7 @@ mod tests { .as_ref() .expect("first create should have succeeded"); assert_eq!(loaded.schema.table_count, 1); - assert!(loaded.store.table_at(&"Other".parse().unwrap()).is_none()); + assert!(loaded.store.table_at(&"Other".into()).is_none()); } #[test] @@ -560,6 +544,6 @@ mod tests { let loaded = session.loaded.as_ref().expect("loaded"); assert_eq!(loaded.schema.table_count, 1); - assert!(loaded.store.table_at(&"Other".parse().unwrap()).is_none()); + assert!(loaded.store.table_at(&"Other".into()).is_none()); } } diff --git a/packages/coln-store/src/solver/compile.rs b/packages/coln-store/src/solver/compile.rs index fae1236d..db8ec07f 100644 --- a/packages/coln-store/src/solver/compile.rs +++ b/packages/coln-store/src/solver/compile.rs @@ -309,20 +309,10 @@ struct DisplayPath<'a>(&'a ir::Path); impl fmt::Display for DisplayPath<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (idx, qname) in self.0.iter().enumerate() { - if idx > 0 { - write!(f, ".")?; - } - write!(f, "{}", display_qname(qname))?; - } - Ok(()) + self.0.fmt(f) } } -fn display_qname(qname: &ir::QName) -> String { - qname.join("/") -} - fn var_name(index: usize) -> String { match index { 0..=25 => ((b'a' + index as u8) as char).to_string(), diff --git a/packages/fnotation/src/FNotation/Pretty.hs b/packages/fnotation/src/FNotation/Pretty.hs index 4ed8cb7a..9aa817a8 100644 --- a/packages/fnotation/src/FNotation/Pretty.hs +++ b/packages/fnotation/src/FNotation/Pretty.hs @@ -95,6 +95,7 @@ prt p = \case Mode x _ -> "^" <> dprettyWithKinds ?lconfig x Int i _ -> pretty i String x _ -> "\"" <> pretty x <> "\"" + Raw x _ -> pretty x Tuple ns _ -> bracketedTuple $ prtTop <$> ns Error _ -> "" diff --git a/packages/fnotation/src/FNotation/Trees.hs b/packages/fnotation/src/FNotation/Trees.hs index ad9738c4..9e15475d 100644 --- a/packages/fnotation/src/FNotation/Trees.hs +++ b/packages/fnotation/src/FNotation/Trees.hs @@ -40,6 +40,7 @@ data NtnGeneric a | Mode Name a | Int Int a | String Text a + | Raw Text a -- This is used for pretty printing, when you just want to include some raw text in the pretty printed output | Error a pattern Decl :: Name -> NtnGeneric a -> a -> NtnGeneric a @@ -73,6 +74,7 @@ startPos (Mode _ s) = s.start startPos (Int _ s) = s.start startPos (String _ s) = s.start startPos (Tuple _ s) = s.start +startPos (Raw _ s) = s.start startPos (Error s) = s.start endPos :: Ntn -> Pos @@ -87,6 +89,7 @@ endPos (Tag _ s) = s.end endPos (Mode _ s) = s.end endPos (Int _ s) = s.end endPos (String _ s) = s.end +endPos (Raw _ s) = s.end endPos (Tuple _ s) = s.end endPos (Error s) = s.end @@ -109,6 +112,7 @@ head (Mode x _) = "Mode" <+> dpretty x head (Int i _) = "Int" <+> pretty i head (String s _) = "String" <+> pretty s head (Tuple _ _) = "Tuple" +head (Raw _ _) = "Raw" head (Error _) = "Error" children :: Ntn -> [Ntn] @@ -124,6 +128,7 @@ children (Mode _ _) = [] children (Int _ _) = [] children (String _ _) = [] children (Tuple ns _) = ns +children (Raw _ _) = [] children (Error _) = [] instance DPretty Ntn where