From 237d0cd66a32d1e80b61da8fa21b7c60b59a851e Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Thu, 7 Sep 2017 07:50:39 -0700 Subject: [PATCH] Comments --- src/IR.purs | 7 +++++++ src/Language/JsonSchema.purs | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/IR.purs b/src/IR.purs index 9fb708b5..13093439 100644 --- a/src/IR.purs +++ b/src/IR.purs @@ -285,12 +285,17 @@ replaceClass from to = do replaceTypes $ (replaceClassesInType \i -> if i == from then Just to else Nothing) deleteClass from +-- This maps from old class index to new class index and new class data type ClassMapper = State (Map Int (Tuple Int (Maybe IRClassData))) normalizeGraphOrder :: IRGraph -> IRGraph normalizeGraphOrder graph@(IRGraph { toplevels }) = evalState work M.empty where + -- When we encounter a class we first check whether we've seen + -- it before (Right), or whether it's new (Left). In the Left + -- case, we get a new index for the class, and the index is added + -- to the map. registerClass :: Int -> ClassMapper (Either Int Int) registerClass oldIndex = do m <- get @@ -301,6 +306,8 @@ normalizeGraphOrder graph@(IRGraph { toplevels }) = put $ M.insert oldIndex (Tuple newIndex Nothing) m pure $ Left newIndex + -- After we're done processing a new class, we update the + -- entry in the map with its IRClassData. setClass :: Int -> IRClassData -> ClassMapper Unit setClass oldIndex cd = do m <- get diff --git a/src/Language/JsonSchema.purs b/src/Language/JsonSchema.purs index 559c6311..704e12f3 100644 --- a/src/Language/JsonSchema.purs +++ b/src/Language/JsonSchema.purs @@ -84,6 +84,21 @@ newtype JSONSchema = JSONSchema , title :: Maybe String } +-- For recursive JSON Schemas we must not reenter a class we've +-- already begun processing. The way we ensure this is to keep +-- a map of the reference paths of all the classes we've encountered +-- so far. It maps to each class's index in the graph. +-- +-- Of course we can only set the entry in the graph properly once +-- we're done with processing the class, but we need to reserve +-- the index when starting processing the class. As a simple solution +-- we just set the entry to `NoType`` when we start, then replace it +-- with the finished `Class`` entry when we're done. +-- +-- FIXME: We don't actually need the IR monad because the path map +-- itself can keep track of the index of each class as well as the +-- number of classes seen so far (which is also the index of the next +-- class to be added). Similar to `normalizeGraphOrder`. type JsonIR = StateT.StateT (Map ReversePath Int) IR decodeEnum :: forall a. StrMap a -> Json -> Either Error a