packages feed

zeolite-lang 0.7.0.0 → 0.7.0.1

raw patch · 20 files changed

+452/−177 lines, 20 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- CompilerCxx.Procedure: compileExpression :: (Show c, CompileErrorM m, MergeableM m, CompilerContext c m [String] a) => Expression c -> CompilerState a m (ExpressionType, ExprValue)
- CompilerCxx.Procedure: compileStatement :: (Show c, CompileErrorM m, MergeableM m, CompilerContext c m [String] a) => Statement c -> CompilerState a m ()
+ Base.CompileError: compileBackgroundM :: CompileErrorM m => String -> m ()
+ Base.CompileError: resetBackgroundM :: CompileErrorM m => m a -> m a
+ Compilation.CompilerState: resetBackgroundStateT :: CompileErrorM m => CompilerState a m b -> CompilerState a m b
+ CompilerCxx.Procedure: compileRegularInit :: (Show c, CompileErrorM m, MergeableM m, CompilerContext c m [String] a) => DefinedMember c -> CompilerState a m ()
+ Types.TypeCategory: getCategoryParamMap :: AnyCategory c -> ParamValues
+ Types.TypeInstance: [jpnFixed] :: TypeInstanceOrParam -> Bool
+ Types.TypeInstance: fixTypeParams :: GeneralInstance -> GeneralInstance
+ Types.TypeInstance: hasInferredParams :: GeneralInstance -> Bool
+ Types.TypeInstance: type ParamValues = Map ParamName GeneralInstance
+ Types.TypeInstance: unfixTypeParams :: GeneralInstance -> GeneralInstance
- Types.Function: assignFunctionParams :: (MergeableM m, CompileErrorM m, TypeResolver r) => r -> ParamFilters -> Positional GeneralInstance -> FunctionType -> m FunctionType
+ Types.Function: assignFunctionParams :: (MergeableM m, CompileErrorM m, TypeResolver r) => r -> ParamFilters -> ParamValues -> Positional GeneralInstance -> FunctionType -> m FunctionType
- Types.Function: checkFunctionConvert :: (MergeableM m, CompileErrorM m, TypeResolver r) => r -> ParamFilters -> FunctionType -> FunctionType -> m ()
+ Types.Function: checkFunctionConvert :: (MergeableM m, CompileErrorM m, TypeResolver r) => r -> ParamFilters -> ParamValues -> FunctionType -> FunctionType -> m ()
- Types.TypeCategory: inferParamTypes :: (MergeableM m, CompileErrorM m, TypeResolver r) => r -> ParamFilters -> Map ParamName GeneralInstance -> [(ValueType, ValueType)] -> m (Map ParamName GeneralInstance)
+ Types.TypeCategory: inferParamTypes :: (MergeableM m, CompileErrorM m, TypeResolver r) => r -> ParamFilters -> ParamFilters -> ParamValues -> [(ValueType, ValueType)] -> m ParamValues
- Types.TypeCategory: mergeFunctions :: (Show c, MergeableM m, CompileErrorM m, TypeResolver r) => r -> CategoryMap c -> ParamFilters -> [ValueRefine c] -> [ValueDefine c] -> [ScopedFunction c] -> m [ScopedFunction c]
+ Types.TypeCategory: mergeFunctions :: (Show c, MergeableM m, CompileErrorM m, TypeResolver r) => r -> CategoryMap c -> ParamValues -> ParamFilters -> [ValueRefine c] -> [ValueDefine c] -> [ScopedFunction c] -> m [ScopedFunction c]
- Types.TypeCategory: uncheckedSubFunction :: (Show c, MergeableM m, CompileErrorM m) => Map ParamName GeneralInstance -> ScopedFunction c -> m (ScopedFunction c)
+ Types.TypeCategory: uncheckedSubFunction :: (Show c, MergeableM m, CompileErrorM m) => ParamValues -> ScopedFunction c -> m (ScopedFunction c)
- Types.TypeInstance: JustParamName :: ParamName -> TypeInstanceOrParam
+ Types.TypeInstance: JustParamName :: Bool -> ParamName -> TypeInstanceOrParam
- Types.TypeInstance: getValueForParam :: CompileErrorM m => Map ParamName GeneralInstance -> ParamName -> m GeneralInstance
+ Types.TypeInstance: getValueForParam :: CompileErrorM m => ParamValues -> ParamName -> m GeneralInstance

Files

ChangeLog.md view
@@ -1,5 +1,21 @@ # Revision history for zeolite-lang +## 0.7.0.1  -- 2020-05-20++### Language++* **[fix]** Fixes an edge-case where type-inference can be influenced by a+  param filter for a param with the same name in the scope that is calling the+  function. (For example, having `#x requires Foo` in scope while calling a+  function that also happens to have a param named `#x`.)++* **[fix]** Fixes an edge-case where parameter substitution at the type level+  can clash with a type parameter scoped to a function. (Related to the above,+  but actually a separate issue discovered while solving the former.)++* **[behavior]** Shows inferred-type assignments in error messages related to+  expressions containing inferred types.+ ## 0.7.0.0  -- 2020-05-19  ### Language
src/Base/CompileError.hs view
@@ -49,6 +49,11 @@   reviseErrorM :: m a -> String -> m a   reviseErrorM e _ = e   compileWarningM :: String -> m ()+  compileWarningM _ = return ()+  compileBackgroundM :: String -> m ()+  compileBackgroundM _ = return ()+  resetBackgroundM :: m a -> m a+  resetBackgroundM = id  mapErrorsM :: CompileErrorM m => (a -> m b) -> [a] -> m [b] mapErrorsM f = collectAllOrErrorM . map f
src/Base/CompileInfo.hs view
@@ -139,6 +139,7 @@   } |   CompileSuccess {     csWarnings :: [String],+    csBackground :: [String],     csData :: a   } @@ -146,27 +147,30 @@   fmap f x = CompileInfoT $ do     x' <- citState x     case x' of-         CompileFail w e    -> return $ CompileFail w e -- Not the same a.-         CompileSuccess w d -> return $ CompileSuccess w (f d)+         CompileFail w e      -> return $ CompileFail w e -- Not the same a.+         CompileSuccess w b d -> return $ CompileSuccess w b (f d)  instance (Applicative m, Monad m) => Applicative (CompileInfoT m) where-  pure = CompileInfoT .return . CompileSuccess []+  pure = CompileInfoT .return . CompileSuccess [] []   f <*> x = CompileInfoT $ do     f' <- citState f     x' <- citState x     case (f',x') of-         (CompileFail w e,     _)                   -> return $ CompileFail w e -- Not the same a.-         (i,                   CompileFail w e)     -> return $ CompileFail (getWarnings i ++ w) e -- Not the same a.-         (CompileSuccess w1 f2,CompileSuccess w2 d) -> return $ CompileSuccess (w1 ++ w2) (f2 d)+         (CompileFail w e,_) ->+           return $ CompileFail w e -- Not the same a.+         (i,CompileFail w e) ->+           return $ CompileFail (getWarnings i ++ w) (addBackground (getBackground i) e)+         (CompileSuccess w1 b1 f2,CompileSuccess w2 b2 d) ->+           return $ CompileSuccess (w1 ++ w2) (b1 ++ b2) (f2 d)  instance Monad m => Monad (CompileInfoT m) where   x >>= f = CompileInfoT $ do     x' <- citState x     case x' of-         CompileFail w e    -> return $ CompileFail w e -- Not the same a.-         CompileSuccess w d -> do+         CompileFail w e -> return $ CompileFail w e -- Not the same a.+         CompileSuccess w b d -> do            d2 <- citState $ f d-           return $ prependWarning w d2+           return $ includeBackground b $ prependWarning w d2   return = pure  #if MIN_VERSION_base(4,9,0)@@ -175,7 +179,7 @@ #endif  instance MonadTrans CompileInfoT where-  lift = CompileInfoT . fmap (CompileSuccess [])+  lift = CompileInfoT . fmap (CompileSuccess [] [])  instance MonadIO m => MonadIO (CompileInfoT m) where   liftIO = lift . liftIO@@ -185,40 +189,57 @@   collectAllOrErrorM xs = CompileInfoT $ do     xs' <- sequence $ map citState $ foldr (:) [] xs     return $ result $ splitErrorsAndData xs' where-      result ([],xs2,ws) = CompileSuccess ws xs2-      result (es,_,ws)   = CompileFail ws $ CompileMessage "" es+      result ([],xs2,bs,ws) = CompileSuccess ws bs xs2+      result (es,_,bs,ws)   = CompileFail ws $ addBackground bs $ CompileMessage "" es   collectOneOrErrorM xs = CompileInfoT $ do     xs' <- sequence $ map citState $ foldr (:) [] xs     return $ result $ splitErrorsAndData xs' where-      result (_,x:_,ws) = CompileSuccess ws x-      result ([],_,ws)  = CompileFail ws $ CompileMessage "" []-      result (es,_,ws)  = CompileFail ws $ CompileMessage "" es+      result (_,x:_,bs,ws) = CompileSuccess ws bs x+      result ([],_,bs,ws)  = CompileFail ws $ addBackground bs $ CompileMessage "" []+      result (es,_,bs,ws)  = CompileFail ws $ addBackground bs $ CompileMessage "" es   reviseErrorM x e2 = CompileInfoT $ do     x' <- citState x     case x' of          CompileFail w (CompileMessage [] ms) -> return $ CompileFail w $ CompileMessage e2 ms          CompileFail w e                      -> return $ CompileFail w $ CompileMessage e2 [e]          x2                                   -> return x2-  compileWarningM w = CompileInfoT (return $ CompileSuccess [w] ())+  compileWarningM w = CompileInfoT (return $ CompileSuccess [w] [] ())+  compileBackgroundM b = CompileInfoT (return $ CompileSuccess [] [b] ())+  resetBackgroundM x = CompileInfoT $ do+    x' <- citState x+    case x' of+         CompileSuccess w _ d -> return $ CompileSuccess w [] d+         x2                   -> return x2  instance Monad m => MergeableM (CompileInfoT m) where   mergeAnyM xs = CompileInfoT $ do     xs' <- sequence $ map citState $ foldr (:) [] xs     return $ result $ splitErrorsAndData xs' where-      result ([],[],ws) = CompileFail ws $ CompileMessage "" []-      result (es,[],ws) = CompileFail ws $ CompileMessage "" es-      result (_,xs2,ws) = CompileSuccess ws (mergeAny xs2)+      result ([],[],bs,ws) = CompileFail ws $ addBackground bs $ CompileMessage "" []+      result (es,[],bs,ws) = CompileFail ws $ addBackground bs $ CompileMessage "" es+      result (_,xs2,bs,ws) = CompileSuccess ws bs (mergeAny xs2)   mergeAllM = collectAllOrErrorM >=> return . mergeAll  getWarnings :: CompileInfoState a -> [String]-getWarnings (CompileFail w _)    = w-getWarnings (CompileSuccess w _) = w+getWarnings (CompileFail w _)      = w+getWarnings (CompileSuccess w _ _) = w  prependWarning :: [String] -> CompileInfoState a -> CompileInfoState a-prependWarning w (CompileSuccess w2 d) = CompileSuccess (w ++ w2) d-prependWarning w (CompileFail w2 e)    = CompileFail (w ++ w2) e+prependWarning w (CompileSuccess w2 b d) = CompileSuccess (w ++ w2) b d+prependWarning w (CompileFail w2 e)      = CompileFail (w ++ w2) e -splitErrorsAndData :: Foldable f => f (CompileInfoState a) -> ([CompileMessage],[a],[String])-splitErrorsAndData = foldr partition ([],[],[]) where-  partition (CompileFail w e)    (es,ds,ws) = (e:es,ds,w++ws)-  partition (CompileSuccess w d) (es,ds,ws) = (es,d:ds,w++ws)+getBackground :: CompileInfoState a -> [String]+getBackground (CompileSuccess _ b _) = b+getBackground _                      = []++includeBackground :: [String] -> CompileInfoState a -> CompileInfoState a+includeBackground b  (CompileFail w e)       = CompileFail w (addBackground b e)+includeBackground b1 (CompileSuccess w b2 d) = CompileSuccess w (b1 ++ b2) d++addBackground :: [String] -> CompileMessage -> CompileMessage+addBackground b (CompileMessage e es) = CompileMessage e (es ++ map (flip CompileMessage []) b)++splitErrorsAndData :: Foldable f => f (CompileInfoState a) -> ([CompileMessage],[a],[String],[String])+splitErrorsAndData = foldr partition ([],[],[],[]) where+  partition (CompileFail w e)      (es,ds,bs,ws) = (e:es,ds,bs,w++ws)+  partition (CompileSuccess w b d) (es,ds,bs,ws) = (es,d:ds,b++bs,w++ws)
src/Compilation/CompilerState.hs view
@@ -60,6 +60,7 @@   csUpdateAssigned,   csWrite,   getCleanContext,+  resetBackgroundStateT,   reviseErrorStateT,   runDataCompiler, ) where@@ -150,6 +151,9 @@  reviseErrorStateT :: (CompileErrorM m) => CompilerState a m b -> String -> CompilerState a m b reviseErrorStateT x s = mapStateT (`reviseErrorM` s) x++resetBackgroundStateT :: (CompileErrorM m) => CompilerState a m b -> CompilerState a m b+resetBackgroundStateT x = mapStateT resetBackgroundM x  csCurrentScope :: CompilerContext c m s a => CompilerState a m SymbolScope csCurrentScope = fmap ccCurrentScope get >>= lift
src/Compilation/ProcedureContext.hs view
@@ -85,7 +85,7 @@   ccCurrentScope = return . pcScope   ccResolver = return . AnyTypeResolver . CategoryResolver . pcCategories   ccSameType ctx = return . (== same) where-    same = TypeInstance (pcType ctx) (fmap (SingleType . JustParamName . vpParam) $ pcExtParams ctx)+    same = TypeInstance (pcType ctx) (fmap (SingleType . JustParamName False . vpParam) $ pcExtParams ctx)   ccAllFilters = return . pcAllFilters   ccGetParamScope ctx p = do     case p `Map.lookup` pcParamScopes ctx of@@ -144,7 +144,7 @@     getFunction (Just ta@(TypeMerge MergeIntersect ts)) =       collectOneOrErrorM (map getFunction $ map Just ts) `reviseErrorM`         ("Function " ++ show n ++ " not available for type " ++ show ta ++ formatFullContextBrace c)-    getFunction (Just (SingleType (JustParamName p))) = do+    getFunction (Just (SingleType (JustParamName _ p))) = do       fa <- ccAllFilters ctx       fs <- case p `Map.lookup` fa of                 (Just fs) -> return fs@@ -156,23 +156,23 @@     getFunction (Just (SingleType (JustTypeInstance t2)))       -- Same category as the procedure itself.       | tiName t2 == pcType ctx =-        checkFunction (tiName t2) (fmap vpParam $ pcExtParams ctx) (tiParams t2) $ n `Map.lookup` pcFunctions ctx+        subAndCheckFunction (tiName t2) (fmap vpParam $ pcExtParams ctx) (tiParams t2) $ n `Map.lookup` pcFunctions ctx       -- A different category than the procedure.       | otherwise = do         (_,ca) <- getCategory (pcCategories ctx) (c,tiName t2)         let params = Positional $ map vpParam $ getCategoryParams ca         let fa = Map.fromList $ map (\f -> (sfName f,f)) $ getCategoryFunctions ca-        checkFunction (tiName t2) params (tiParams t2) $ n `Map.lookup` fa+        subAndCheckFunction (tiName t2) params (tiParams t2) $ n `Map.lookup` fa     getFunction Nothing = do-      let ps = fmap (SingleType . JustParamName . vpParam) $ pcExtParams ctx+      let ps = fmap (SingleType . JustParamName False . vpParam) $ pcExtParams ctx       getFunction (Just $ SingleType $ JustTypeInstance $ TypeInstance (pcType ctx) ps)     getFunction (Just t2) = compileErrorM $ "Type " ++ show t2 ++ " contains unresolved types"     checkDefine t2 = do       (_,ca) <- getCategory (pcCategories ctx) (c,diName t2)       let params = Positional $ map vpParam $ getCategoryParams ca       let fa = Map.fromList $ map (\f -> (sfName f,f)) $ getCategoryFunctions ca-      checkFunction (diName t2) params (diParams t2) $ n `Map.lookup` fa-    checkFunction t2 ps1 ps2 (Just f) = do+      subAndCheckFunction (diName t2) params (diParams t2) $ n `Map.lookup` fa+    subAndCheckFunction t2 ps1 ps2 (Just f) = do       when (pcDisallowInit ctx && t2 == pcType ctx) $         compileErrorM $ "Function " ++ show n ++                        " disallowed during initialization" ++ formatFullContextBrace c@@ -183,7 +183,7 @@         ("In external function call at " ++ formatFullContext c)       let assigned = Map.fromList paired       uncheckedSubFunction assigned f-    checkFunction t2 _ _ _ =+    subAndCheckFunction t2 _ _ _ =       compileErrorM $ "Category " ++ show t2 ++                      " does not have a type or value function named " ++ show n ++                      formatFullContextBrace c
src/Compilation/ScopeContext.hs view
@@ -71,7 +71,7 @@   (_,t) <- getConcreteCategory ta (c,n)   let params = Positional $ getCategoryParams t   let params2 = Positional pi-  let typeInstance = TypeInstance n $ fmap (SingleType . JustParamName . vpParam) params+  let typeInstance = TypeInstance n $ fmap (SingleType . JustParamName False . vpParam) params   let filters = getCategoryFilters t   let filters2 = fi   let r = CategoryResolver ta
src/CompilerCxx/Category.hs view
@@ -300,24 +300,36 @@   (_,t) <- getConcreteCategory ta (c,n)   let r = CategoryResolver ta   [cp,tp,vp] <- getProcedureScopes ta em dd-  cf <- collectAllOrErrorM $ applyProcedureScope compileExecutableProcedure cp-  tf <- collectAllOrErrorM $ applyProcedureScope compileExecutableProcedure tp-  vf <- collectAllOrErrorM $ applyProcedureScope compileExecutableProcedure vp+  let (cm,tm,vm) = partitionByScope dmScope ms+  let filters = getCategoryFilters t+  let filters2 = fi+  let allFilters = getFilterMap (getCategoryParams t ++ pi) $ filters ++ filters2   -- Functions explicitly declared externally.   let externalFuncs = Set.fromList $ map sfName $ filter ((== n) . sfType) $ getCategoryFunctions t   -- Functions explicitly declared internally.   let overrideFuncs = Map.fromList $ map (\f -> (sfName f,f)) fs   -- Functions only declared internally.   let internalFuncs = Map.filter (not . (`Set.member` externalFuncs) . sfName) overrideFuncs-  let (cm,tm,vm) = partitionByScope dmScope ms+  let fe = Map.elems internalFuncs+  let allFuncs = getCategoryFunctions t ++ fe+  cf <- collectAllOrErrorM $ applyProcedureScope compileExecutableProcedure cp+  ce <- mergeAllM [+      categoryConstructor t cm,+      categoryDispatch allFuncs,+      return $ mergeAll $ map fst cf,+      mergeAllM $ map (createMemberLazy r allFilters) cm+    ]+  tf <- collectAllOrErrorM $ applyProcedureScope compileExecutableProcedure tp   disallowTypeMembers tm+  te <- mergeAllM [+      typeConstructor t tm,+      typeDispatch allFuncs,+      return $ mergeAll $ map fst tf,+      mergeAllM $ map (createMember r allFilters) tm+    ]+  vf <- collectAllOrErrorM $ applyProcedureScope compileExecutableProcedure vp   let internalCount = length pi   let memberCount = length vm-  let fe = Map.elems internalFuncs-  let allFuncs = getCategoryFunctions t ++ fe-  let filters = getCategoryFilters t-  let filters2 = fi-  let allFilters = getFilterMap (getCategoryParams t ++ pi) $ filters ++ filters2   top <- mergeAllM [       return $ onlyCode $ "class " ++ valueName n ++ ";",       declareInternalValue n internalCount memberCount@@ -338,18 +350,6 @@       return $ defineValue,       defineInternalValue n internalCount memberCount     ] ++ map (return . snd) (cf ++ tf ++ vf)-  ce <- mergeAllM [-      categoryConstructor t cm,-      categoryDispatch allFuncs,-      return $ mergeAll $ map fst cf,-      mergeAllM $ map (createMemberLazy r allFilters) cm-    ]-  te <- mergeAllM [-      typeConstructor t tm,-      typeDispatch allFuncs,-      return $ mergeAll $ map fst tf,-      mergeAllM $ map (createMember r allFilters) tm-    ]   commonDefineAll t ns rs top bottom ce te fe   where     disallowTypeMembers :: (Show c, CompileErrorM m, MergeableM m) =>@@ -388,7 +388,7 @@       let initPassed = map (\(i,p) -> paramName p ++ "(*std::get<" ++ show i ++ ">(params))") $ zip ([0..] :: [Int]) ps2       let allInit = intercalate ", " $ initParent:initPassed       ctx <- getContextForInit ta em t dd TypeScope-      initMembers <- runDataCompiler (sequence $ map initMember ms2) ctx+      initMembers <- runDataCompiler (sequence $ map compileRegularInit ms2) ctx       mergeAllM [           return $ onlyCode $ typeName n ++ "(" ++ allArgs ++ ") : " ++ allInit ++ " {",           return $ indentCompiled $ onlyCodes $ getCycleCheck (typeName n),@@ -415,11 +415,6 @@       validateGeneralInstance r filters (vtType $ dmType m) `reviseErrorM`         ("In creation of " ++ show (dmName m) ++ " at " ++ formatFullContext (dmContext m))       return $ onlyCode $ variableLazyType (dmType m) ++ " " ++ variableName (dmName m) ++ ";"-    initMember (DefinedMember _ _ _ _ Nothing) = return mergeDefault-    initMember (DefinedMember c2 s t n2 (Just e)) = do-      csAddVariable c2 n2 (VariableValue c2 s t True)-      let assign = Assignment c2 (Positional [ExistingVariable (InputValue c2 n2)]) e-      compileStatement assign     categoryDispatch fs2 =       return $ onlyCodes $ [           "ReturnTuple Dispatch(" ++@@ -637,7 +632,7 @@           "const TypeCategory& category, " ++           "std::vector<const TypeInstance*>& args) const final {"         ] ++ allCats rs2 ++ ["  return false;","}"]-    myType = (getCategoryName t,map (SingleType . JustParamName . fst) params)+    myType = (getCategoryName t,map (SingleType . JustParamName False . fst) params)     refines rs2 = map (\r -> (tiName r,pValues $ tiParams r)) $ map vrType rs2     allCats rs2 = concat $ map singleCat (myType:refines rs2)     singleCat (t2,ps) = [@@ -663,7 +658,7 @@   typeGetter t ++ "(T_get(" ++ intercalate "," (map ("&" ++) ps') ++ "))"   where     ps' = map expandLocalType $ pValues ps-expandLocalType (SingleType (JustParamName p)) = paramName p+expandLocalType (SingleType (JustParamName _ p)) = paramName p expandLocalType _ = undefined  -- The instance is an InferredType.  defineCategoryName :: CategoryName -> CompiledData [String]
src/CompilerCxx/CategoryContext.hs view
@@ -55,7 +55,7 @@   let sa = Map.fromList $ zip (map vpParam $ getCategoryParams t) (repeat TypeScope)   let r = CategoryResolver tm   fa <- setInternalFunctions r t (dcFunctions d)-  let typeInstance = TypeInstance (getCategoryName t) $ fmap (SingleType . JustParamName . vpParam) ps+  let typeInstance = TypeInstance (getCategoryName t) $ fmap (SingleType . JustParamName False . vpParam) ps   let builtin = Map.filter ((== LocalScope) . vvScope) $ builtinVariables typeInstance   members <- mapMembers $ filter ((<= s) . dmScope) (dcMembers d)   return $ ProcedureContext {
src/CompilerCxx/Procedure.hs view
@@ -27,9 +27,8 @@   categoriesFromRefine,   compileExecutableProcedure,   compileMainProcedure,-  compileExpression,   compileLazyInit,-  compileStatement,+  compileRegularInit, ) where  import Control.Applicative ((<|>))@@ -138,7 +137,7 @@                      CompilerContext c m [String] a) =>   a -> [c] -> Expression c -> CompilerState a m String compileCondition ctx c e = do-  (e',ctx') <- lift $ runStateT compile ctx+  (e',ctx') <- resetBackgroundStateT $ lift $ runStateT compile ctx   lift (ccGetRequired ctx') >>= csRequiresTypes   noTrace <- csGetNoTrace   if noTrace@@ -160,8 +159,12 @@                      CompilerContext c m [String] a) =>   a -> Procedure c -> CompilerState a m a compileProcedure ctx (Procedure _ ss) = do-  ctx' <- lift $ execStateT (sequence $ map (\s -> warnUnreachable s >> compileStatement s) ss) ctx+  ctx' <- lift $ execStateT (sequence $ map compileOne ss) ctx   return ctx' where+    compileOne s = do+      warnUnreachable s+      s' <- resetBackgroundStateT $ compileStatement s+      return s'     warnUnreachable s = do       unreachable <- csIsUnreachable       lift $ when unreachable $@@ -233,19 +236,18 @@   (_,e') <- compileExpression e   maybeSetTrace c   csWrite ["(void) (" ++ useAsWhatever e' ++ ");"]-compileStatement (Assignment c as e) = do+compileStatement (Assignment c as e) = flip reviseErrorStateT message $ do   (ts,e') <- compileExpression e   r <- csResolver   fa <- csAllFilters   -- Check for a count match first, to avoid the default error message.-  _ <- processPairsT alwaysPair (fmap assignableName as) ts `reviseErrorStateT`-    ("In assignment at " ++ formatFullContext c)-  _ <- processPairsT (createVariable r fa) as ts `reviseErrorStateT`-    ("In assignment at " ++ formatFullContext c)+  _ <- processPairsT alwaysPair (fmap assignableName as) ts+  _ <- processPairsT (createVariable r fa) as ts   maybeSetTrace c   variableTypes <- sequence $ map (uncurry getVariableType) $ zip (pValues as) (pValues ts)   assignAll (zip3 ([0..] :: [Int]) variableTypes (pValues as)) e'   where+    message = "In assignment at " ++ formatFullContext c     assignAll [v] e2 = assignSingle v e2     assignAll vs e2 = do       csWrite ["{","const auto r = " ++ useAsReturns e2 ++ ";"]@@ -256,21 +258,21 @@       (VariableValue _ _ t _) <- csGetVariable c2 n       return t     getVariableType (ExistingVariable (DiscardInput _)) t = return t-    createVariable r fa (CreateVariable c2 t1 n) t2 = do-      -- TODO: Call csRequiresTypes for t1. (Maybe needs a helper function.)-      lift $ mergeAllM [validateGeneralInstance r fa (vtType t1),-                        checkValueTypeMatch_ r fa t2 t1] `reviseErrorM`-        ("In creation of " ++ show n ++ " at " ++ formatFullContext c2)-      csAddVariable c2 n (VariableValue c2 LocalScope t1 True)-      csWrite [variableStoredType t1 ++ " " ++ variableName n ++ ";"]-    createVariable r fa (ExistingVariable (InputValue c2 n)) t2 = do-      (VariableValue _ _ t1 w) <- csGetVariable c2 n-      when (not w) $ lift $ compileErrorM $ "Cannot assign to read-only variable " ++-                                           show n ++ formatFullContextBrace c2-      -- TODO: Also show original context.-      lift $ (checkValueTypeMatch_ r fa t2 t1) `reviseErrorM`-        ("In assignment to " ++ show n ++ " at " ++ formatFullContext c2)-      csUpdateAssigned n+    createVariable r fa (CreateVariable c2 t1 n) t2 =+      flip reviseErrorStateT ("In creation of " ++ show n ++ " at " ++ formatFullContext c2) $ do+        -- TODO: Call csRequiresTypes for t1. (Maybe needs a helper function.)+        lift $ mergeAllM [validateGeneralInstance r fa (vtType t1),+                          checkValueTypeMatch_ r fa t2 t1]+        csAddVariable c2 n (VariableValue c2 LocalScope t1 True)+        csWrite [variableStoredType t1 ++ " " ++ variableName n ++ ";"]+    createVariable r fa (ExistingVariable (InputValue c2 n)) t2 =+      flip reviseErrorStateT ("In assignment to " ++ show n ++ " at " ++ formatFullContext c2) $ do+        (VariableValue _ _ t1 w) <- csGetVariable c2 n+        when (not w) $ lift $ compileErrorM $ "Cannot assign to read-only variable " +++                                              show n ++ formatFullContextBrace c2+        -- TODO: Also show original context.+        lift $ (checkValueTypeMatch_ r fa t2 t1)+        csUpdateAssigned n     createVariable _ _ _ _ = return ()     assignSingle (_,t,CreateVariable _ _ n) e2 =       csWrite [variableName n ++ " = " ++ writeStoredVariable t e2 ++ ";"]@@ -290,11 +292,20 @@     assignMulti _ = return () compileStatement (NoValueExpression _ v) = compileVoidExpression v +compileRegularInit :: (Show c, CompileErrorM m, MergeableM m,+                       CompilerContext c m [String] a) =>+  DefinedMember c -> CompilerState a m ()+compileRegularInit (DefinedMember _ _ _ _ Nothing) = return mergeDefault+compileRegularInit (DefinedMember c2 s t n2 (Just e)) = resetBackgroundStateT $ do+  csAddVariable c2 n2 (VariableValue c2 s t True)+  let assign = Assignment c2 (Positional [ExistingVariable (InputValue c2 n2)]) e+  compileStatement assign+ compileLazyInit :: (Show c, CompileErrorM m, MergeableM m,                    CompilerContext c m [String] a) =>   DefinedMember c -> CompilerState a m () compileLazyInit (DefinedMember _ _ _ _ Nothing) = return mergeDefault-compileLazyInit (DefinedMember c _ t1 n (Just e)) = do+compileLazyInit (DefinedMember c _ t1 n (Just e)) = resetBackgroundStateT $ do   (ts,e') <- compileExpression e   when (length (pValues ts) /= 1) $     lift $ compileErrorM $ "Expected single return in initializer" ++ formatFullContextBrace (getExpressionContext e)@@ -804,8 +815,9 @@   es' <- sequence $ map compileExpression $ pValues es   (ts,es'') <- getValues es'   ps2 <- lift $ guessParamsFromArgs r fa f ps (Positional ts)+  lift $ mergeAllM $ map backgroundMessage $ zip3 (map vpParam $ pValues $ sfParams f) (pValues ps) (pValues ps2)   f' <- lift $ parsedToFunctionType f-  f'' <- lift $ assignFunctionParams r fa ps2 f'+  f'' <- lift $ assignFunctionParams r fa Map.empty ps2 f'   -- Called an extra time so arg count mismatches have reasonable errors.   lift $ processPairs_ (\_ _ -> return ()) (ftArgs f'') (Positional ts)   lift $ processPairs_ (checkArg r fa) (ftArgs f'') (Positional $ zip ([0..] :: [Int]) ts)@@ -817,6 +829,10 @@   return $ (ftReturns f'',OpaqueMulti call)   where     errorContext = "In call to " ++ show (sfName f) ++ " at " ++ formatFullContext c+    backgroundMessage (n,(InferredInstance c2),t) =+      compileBackgroundM $ "Parameter " ++ show n ++ " (from " ++ show (sfType f) ++ "." +++        show (sfName f) ++ ") inferred as " ++ show t ++ " at " ++ formatFullContext c2+    backgroundMessage _ = return ()     assemble Nothing _ ValueScope ps2 es2 =       return $ callName (sfName f) ++ "(Var_self, " ++ ps2 ++ ", " ++ es2 ++ ")"     assemble Nothing scoped _ ps2 es2 =@@ -843,11 +859,10 @@   r -> ParamFilters -> ScopedFunction c -> Positional (InstanceOrInferred c) ->   Positional ValueType -> m (Positional GeneralInstance) guessParamsFromArgs r fa f ps ts = do-  let fa2 = fa `Map.union` getFunctionFilterMap f+  let ff = getFunctionFilterMap f   args <- processPairs alwaysPair ts (fmap pvType $ sfArgs f)   pa <- fmap Map.fromList $ processPairs toInstance (fmap vpParam $ sfParams f) ps-  let pa2 = pa `Map.union` (Map.fromList $ zip (Map.keys fa2) (map (SingleType . JustParamName) $ Map.keys fa2))-  pa3 <- inferParamTypes r fa2 pa2 args+  pa3 <- inferParamTypes r fa ff pa args   fmap Positional $ mapErrorsM (subPosition pa3) (pValues $ sfParams f) where     subPosition pa2 p =       case (vpParam p) `Map.lookup` pa2 of@@ -920,7 +935,7 @@ expandGeneralInstance (SingleType (JustTypeInstance (TypeInstance t ps))) = do   ps' <- sequence $ map expandGeneralInstance $ pValues ps   return $ typeGetter t ++ "(T_get(" ++ intercalate "," (map ("&" ++) ps') ++ "))"-expandGeneralInstance (SingleType (JustParamName p)) = do+expandGeneralInstance (SingleType (JustParamName _ p)) = do   s <- csGetParamScope p   scoped <- autoScope s   return $ scoped ++ paramName p
src/Parser/TypeInstance.hs view
@@ -116,7 +116,7 @@   sourceParser = try param <|> inst where     param = labeled "param" $ do       n <- sourceParser-      return $ JustParamName n+      return $ JustParamName False n     inst = labeled "type" $ do       t <- sourceParser       return $ JustTypeInstance t
src/Test/CompileInfo.hs view
@@ -53,7 +53,26 @@      checkSuccess ['a','b']  (sequence [return 'a',return 'b']),     checkSuccess []         (sequence [] :: CompileInfoIO [Char]),-    checkError   "error1\n" (sequence [compileErrorM "error1",return 'b',compileErrorM "error2"])+    checkError   "error1\n" (sequence [compileErrorM "error1",return 'b',compileErrorM "error2"]),++    checkSuccess 'a' (return 'a' `reviseErrorM` "message"),+    checkError "message\n  error\n" (compileErrorM "error" `reviseErrorM` "message" :: CompileInfoIO ()),++    checkSuccess 'a' (compileBackgroundM "background" >> return 'a'),+    checkError "error\n  background\n"+      (compileBackgroundM "background" >> compileErrorM "error" :: CompileInfoIO ()),+    checkError "error\n  background\n"+      (collectAllOrErrorM [compileBackgroundM "background"] >> compileErrorM "error" :: CompileInfoIO [()]),+    checkError "error\n  background\n"+      (collectOneOrErrorM [compileBackgroundM "background"] >> compileErrorM "error" :: CompileInfoIO ()),+    checkError "error\n  background\n"+      (mergeAllM [compileBackgroundM "background"] >> compileErrorM "error" :: CompileInfoIO ()),+    checkError "error\n  background\n"+      (mergeAnyM [compileBackgroundM "background"] >> compileErrorM "error" :: CompileInfoIO ()),++    checkSuccess 'a' ((resetBackgroundM $ compileBackgroundM "background") >> return 'a'),+    checkError "error\n"+      ((resetBackgroundM $ compileBackgroundM "background") >> compileErrorM "error" :: CompileInfoIO ())   ]  checkSuccess :: (Eq a, Show a) => a -> CompileInfoIO a -> IO (CompileInfo ())
src/Test/TypeCategory.hs view
@@ -1148,7 +1148,7 @@   weakLookup tm2 n =     case n `Map.lookup` tm2 of          Just t  -> return t-         Nothing -> return $ SingleType $ JustParamName n+         Nothing -> return $ SingleType $ JustParamName True n   filterSub im (k,fs) = do     fs' <- mapErrorsM (uncheckedSubFilter (weakLookup im)) fs     return (k,fs')
src/Test/TypeInstance.hs view
@@ -802,7 +802,7 @@   weakLookup tm n =     case n `Map.lookup` tm of          Just t  -> return t-         Nothing -> return $ SingleType $ JustParamName n+         Nothing -> return $ SingleType $ JustParamName True n   filterSub im (k,fs) = do     fs' <- mapErrorsM (uncheckedSubFilter (weakLookup im)) fs     return (k,fs')
src/Types/DefinedCategory.hs view
@@ -83,7 +83,8 @@   m (Map.Map FunctionName (ScopedFunction c)) setInternalFunctions r t fs = foldr update (return start) fs where   start = Map.fromList $ map (\f -> (sfName f,f)) $ getCategoryFunctions t-  filters = getCategoryFilterMap t+  fm = getCategoryFilterMap t+  pm = getCategoryParamMap t   update f@(ScopedFunction c n t2 s as rs ps fs2 ms) fa = do     validateCategoryFunction r t f     fa' <- fa@@ -94,7 +95,7 @@                              "\n  ->\n" ++ show f ++ "\n---\n") $ do              f0' <- parsedToFunctionType f0              f' <- parsedToFunctionType f-             checkFunctionConvert r filters f0' f'+             checkFunctionConvert r fm pm f0' f'            return $ Map.insert n (ScopedFunction (c++c2) n t2 s as rs ps fs2 ([f0]++ms++ms2)) fa'  pairProceduresToFunctions :: (Show c, CompileErrorM m, MergeableM m) =>@@ -170,11 +171,12 @@   let tm' = Map.insert (dcName d) c2 tm   let r = CategoryResolver tm'   let fm = getCategoryFilterMap t+  let pm = getCategoryParamMap t   rs' <- mergeRefines r fm (rs++rs2)   noDuplicateRefines [] n rs'   ds' <- mergeDefines r fm (ds++ds2)   noDuplicateDefines [] n ds'-  fs' <- mergeFunctions r tm' fm rs' ds' fs+  fs' <- mergeFunctions r tm' pm fm rs' ds' fs   let c2' = ValueConcrete c ns n ps rs' ds' vs fs'   let tm0 = (dcName d) `Map.delete` tm   checkCategoryInstances tm0 [c2']
src/Types/Function.hs view
@@ -96,35 +96,34 @@       validateInstanceVariance r allVariances Covariant t  assignFunctionParams :: (MergeableM m, CompileErrorM m, TypeResolver r) =>-  r -> ParamFilters -> Positional GeneralInstance ->+  r -> ParamFilters -> ParamValues -> Positional GeneralInstance ->   FunctionType -> m FunctionType-assignFunctionParams r fm ts (FunctionType as rs ps fa) = do+assignFunctionParams r fm pm ts (FunctionType as rs ps fa) = do   mergeAllM $ map (validateGeneralInstance r fm) $ pValues ts   assigned <- fmap Map.fromList $ processPairs alwaysPair ps ts-  let allAssigned = Map.union assigned (Map.fromList $ map (\n -> (n,SingleType $ JustParamName n)) $ Map.keys fm)-  fa' <- fmap Positional $ mapErrorsM (assignFilters allAssigned) (pValues fa)+  let pa = pm `Map.union` assigned+  fa' <- fmap Positional $ mapErrorsM (assignFilters pa) (pValues fa)   processPairs_ (validateAssignment r fm) ts fa'   as' <- fmap Positional $-         mapErrorsM (uncheckedSubValueType $ getValueForParam allAssigned) (pValues as)+         mapErrorsM (uncheckedSubValueType $ getValueForParam pa) (pValues as)   rs' <- fmap Positional $-         mapErrorsM (uncheckedSubValueType $ getValueForParam allAssigned) (pValues rs)+         mapErrorsM (uncheckedSubValueType $ getValueForParam pa) (pValues rs)   return $ FunctionType as' rs' (Positional []) (Positional [])   where     assignFilters fm2 fs = mapErrorsM (uncheckedSubFilter $ getValueForParam fm2) fs  checkFunctionConvert :: (MergeableM m, CompileErrorM m, TypeResolver r) =>-  r -> ParamFilters -> FunctionType -> FunctionType -> m ()-checkFunctionConvert r fm (FunctionType as1 rs1 ps1 fa1) ff2 = do+  r -> ParamFilters -> ParamValues -> FunctionType -> FunctionType -> m ()+checkFunctionConvert r fm pm (FunctionType as1 rs1 ps1 fa1) ff2 = do   mapped <- fmap Map.fromList $ processPairs alwaysPair ps1 fa1   let fm' = Map.union fm mapped-  let asTypes = Positional $ map (SingleType . JustParamName) $ pValues ps1+  let asTypes = Positional $ map (SingleType . JustParamName False) $ pValues ps1   -- Substitute params from ff2 into ff1.-  (FunctionType as2 rs2 _ _) <- assignFunctionParams r fm' asTypes ff2+  (FunctionType as2 rs2 _ _) <- assignFunctionParams r fm' pm asTypes ff2   fixed <- processPairs alwaysPair ps1 fa1   let fm'' = Map.union fm (Map.fromList fixed)   processPairs_ (validateArg fm'') as1 as2   processPairs_ (validateReturn fm'') rs1 rs2-  return ()   where     validateArg fm2 a1 a2 = checkValueTypeMatch r fm2 a1 a2     validateReturn fm2 r1 r2 = checkValueTypeMatch r fm2 r2 r1
src/Types/TypeCategory.hs view
@@ -48,6 +48,7 @@   getCategoryFunctions,   getCategoryName,   getCategoryNamespace,+  getCategoryParamMap,   getCategoryParams,   getCategoryRefines,   getConcreteCategory,@@ -78,7 +79,7 @@ ) where  import Control.Arrow (second)-import Control.Monad (when)+import Control.Monad ((>=>),when) import Data.List (group,groupBy,intercalate,sort,sortBy) import qualified Data.Map as Map import qualified Data.Set as Set@@ -393,7 +394,7 @@             _ -> return []  subAllParams :: (MergeableM m, CompileErrorM m) =>-  Map.Map ParamName GeneralInstance -> GeneralInstance -> m GeneralInstance+  ParamValues -> GeneralInstance -> m GeneralInstance subAllParams pa = uncheckedSubInstance (getValueForParam pa)  type CategoryMap c = Map.Map CategoryName (AnyCategory c)@@ -470,6 +471,10 @@ getCategoryFilterMap :: AnyCategory c -> ParamFilters getCategoryFilterMap t = getFilterMap (getCategoryParams t) (getCategoryFilters t) +getCategoryParamMap :: AnyCategory c -> ParamValues+getCategoryParamMap t = let ps = map vpParam $ getCategoryParams t in+                          Map.fromList $ zip ps (map (SingleType . JustParamName False) ps)+ -- TODO: Use this where it's needed in this file. getFunctionFilterMap :: ScopedFunction c -> ParamFilters getFunctionFilterMap f = getFilterMap (pValues $ sfParams f) (sfFilters f)@@ -750,16 +755,18 @@       return (ts2 ++ [t'],Map.insert (getCategoryName t') t' tm)     updateSingle r tm t@(ValueInterface c ns n ps rs vs fs) = do       let fm = getCategoryFilterMap t+      let pm = getCategoryParamMap t       rs' <- fmap concat $ mapErrorsM (getRefines tm) rs       rs'' <- mergeRefines r fm rs'       noDuplicateRefines c n rs''       checkMerged r fm rs rs''       -- Only merge from direct parents.-      fs' <- mergeFunctions r tm fm rs [] fs+      fs' <- mergeFunctions r tm pm fm rs [] fs       return $ ValueInterface c ns n ps rs'' vs fs'     -- TODO: Remove duplication below and/or have separate tests.     updateSingle r tm t@(ValueConcrete c ns n ps rs ds vs fs) = do       let fm = getCategoryFilterMap t+      let pm = getCategoryParamMap t       rs' <- fmap concat $ mapErrorsM (getRefines tm) rs       rs'' <- mergeRefines r fm rs'       noDuplicateRefines c n rs''@@ -767,7 +774,7 @@       ds' <- mergeDefines r fm ds       noDuplicateDefines c n ds'       -- Only merge from direct parents.-      fs' <- mergeFunctions r tm fm rs ds fs+      fs' <- mergeFunctions r tm pm fm rs ds fs       return $ ValueConcrete c ns n ps rs'' ds' vs fs'     updateSingle _ _ t = return t     getRefines tm ra@(ValueRefine c t@(TypeInstance n _)) = do@@ -796,29 +803,33 @@     checkConvert _ _ _ _ = return ()  mergeFunctions :: (Show c, MergeableM m, CompileErrorM m, TypeResolver r) =>-  r -> CategoryMap c -> ParamFilters -> [ValueRefine c] ->+  r -> CategoryMap c -> ParamValues -> ParamFilters -> [ValueRefine c] ->   [ValueDefine c] -> [ScopedFunction c] -> m [ScopedFunction c]-mergeFunctions r tm fm rs ds fs = do+mergeFunctions r tm pm fm rs ds fs = do   inheritValue <- fmap concat $ mapErrorsM (getRefinesFuncs tm) rs   inheritType  <- fmap concat $ mapErrorsM (getDefinesFuncs tm) ds   let inheritByName  = Map.fromListWith (++) $ map (\f -> (sfName f,[f])) $ inheritValue ++ inheritType   let explicitByName = Map.fromListWith (++) $ map (\f -> (sfName f,[f])) fs   let allNames = Set.toList $ Set.union (Map.keysSet inheritByName) (Map.keysSet explicitByName)   mapErrorsM (mergeByName r fm inheritByName explicitByName) allNames where-    getRefinesFuncs tm2 ra@(ValueRefine c (TypeInstance n ts2)) = flip reviseErrorM (show ra) $ do+    getRefinesFuncs tm2 (ValueRefine c (TypeInstance n ts2)) = do       (_,t) <- getValueCategory tm2 (c,n)       let ps = map vpParam $ getCategoryParams t       let fs2 = getCategoryFunctions t       paired <- processPairs alwaysPair (Positional ps) ts2       let assigned = Map.fromList paired-      mapErrorsM (uncheckedSubFunction assigned) fs2-    getDefinesFuncs tm2 da@(ValueDefine c (DefinesInstance n ts2)) = flip reviseErrorM (show da) $  do+      mapErrorsM (subFunction assigned) fs2+    getDefinesFuncs tm2 (ValueDefine c (DefinesInstance n ts2)) = do       (_,t) <- getInstanceCategory tm2 (c,n)       let ps = map vpParam $ getCategoryParams t       let fs2 = getCategoryFunctions t       paired <- processPairs alwaysPair (Positional ps) ts2       let assigned = Map.fromList paired-      mapErrorsM (uncheckedSubFunction assigned) fs2+      mapErrorsM (subFunction assigned) fs2+    -- uncheckedSubFunction fixes params so that subsequent substitutions of the+    -- function's own params can't cause a name clash. unfixFunctionParams+    -- un-fixes them so that actual substitution later will succeed.+    subFunction as = uncheckedSubFunction as >=> return . unfixFunctionParams     mergeByName r2 fm2 im em n =       tryMerge r2 fm2 n (n `Map.lookup` im) (n `Map.lookup` em)     -- Inherited without an override.@@ -849,7 +860,7 @@                                 "\n  ->\n" ++ show f1 ++ "\n---\n") $ do                 f1' <- parsedToFunctionType f1                 f2' <- parsedToFunctionType f2-                checkFunctionConvert r3 fm3 f2' f1'+                checkFunctionConvert r3 fm3 pm f2' f1'  data FunctionName =   FunctionName {@@ -937,11 +948,11 @@            _ -> []  uncheckedSubFunction :: (Show c, MergeableM m, CompileErrorM m) =>-  Map.Map ParamName GeneralInstance -> ScopedFunction c -> m (ScopedFunction c)+  ParamValues -> ScopedFunction c -> m (ScopedFunction c) uncheckedSubFunction pa ff@(ScopedFunction c n t s as rs ps fa ms) =   flip reviseErrorM ("In function:\n---\n" ++ show ff ++ "\n---\n") $ do-    let fixed = Map.fromList $ map (\n2 -> (n2,SingleType $ JustParamName n2)) $ map vpParam $ pValues ps-    let pa' = Map.union pa fixed+    let unresolved = Map.fromList $ map (\n2 -> (n2,SingleType $ JustParamName False n2)) $ map vpParam $ pValues ps+    let pa' = (fmap fixTypeParams pa) `Map.union` unresolved     as' <- fmap Positional $ mapErrorsM (subPassed pa') $ pValues as     rs' <- fmap Positional $ mapErrorsM (subPassed pa') $ pValues rs     fa' <- mapErrorsM (subFilter pa') fa@@ -955,16 +966,34 @@         f' <- uncheckedSubFilter (getValueForParam pa2) f         return $ ParamFilter c2 n2 f' +unfixFunctionParams :: ScopedFunction c -> ScopedFunction c+unfixFunctionParams (ScopedFunction c n t s as rs ps fa ms) = updated where+  updated = ScopedFunction c n t s as2 rs2 ps fa2 ms2+  as2 = fmap unfixPassed as+  rs2 = fmap unfixPassed rs+  fa2 = map unfixFilter fa+  ms2 = map unfixFunctionParams ms+  unfixPassed (PassedValue c2 (ValueType r t2)) = PassedValue c2 (ValueType r (unfixTypeParams t2))+  unfixFilter (ParamFilter c2 n2 (TypeFilter d (JustTypeInstance t2))) =+    ParamFilter c2 n2 (TypeFilter d (JustTypeInstance (unfixInstance t2)))+  unfixFilter (ParamFilter c2 n2 (TypeFilter d (JustParamName _ n3))) =+    ParamFilter c2 n2 (TypeFilter d (JustParamName False n3))+  unfixFilter (ParamFilter c2 n2 (DefinesFilter t2)) =+    ParamFilter c2 n2 (DefinesFilter (unfixDefines t2))+  unfixFilter f = f+  unfixInstance (TypeInstance    t2 ps2) = TypeInstance    t2 (fmap unfixTypeParams ps2)+  unfixDefines  (DefinesInstance t2 ps2) = DefinesInstance t2 (fmap unfixTypeParams ps2)+ inferParamTypes :: (MergeableM m, CompileErrorM m, TypeResolver r) =>-  r -> ParamFilters -> Map.Map ParamName GeneralInstance ->-  [(ValueType,ValueType)] -> m (Map.Map ParamName GeneralInstance)-inferParamTypes r f ps ts = do+  r -> ParamFilters -> ParamFilters -> ParamValues ->+  [(ValueType,ValueType)] -> m (ParamValues)+inferParamTypes r f ff ps ts = do   ts2 <- mapErrorsM subAll ts-  f2  <- fmap Map.fromList $ mapErrorsM filterSub $ Map.toList f-  gs  <- mergeAllM $ map (uncurry $ checkValueTypeMatch r f2) ts2-  let gs2 = concat $ map (filtersToGuess f2) $ Map.elems ps+  ff2 <- fmap Map.fromList $ mapErrorsM filterSub $ Map.toList ff+  gs  <- mergeAllM $ map (uncurry $ checkValueTypeMatch r f) ts2+  let gs2 = concat $ map (filtersToGuess ff2) $ Map.elems ps   let gs3 = mergeAll $ gs:(map mergeLeaf gs2)-  gs4 <- mergeInferredTypes r f2 gs3+  gs4 <- mergeInferredTypes r f gs3   let ga = Map.fromList $ zip (map itgParam gs4) (map itgGuess gs4)   return $ ga `Map.union` ps where     subAll (t1,t2) = do@@ -978,16 +1007,18 @@            Nothing -> []            Just fs -> concat $ map (filterToGuess p) fs     filtersToGuess _ _ = []-    filterToGuess p (TypeFilter FilterRequires t) =-      [InferredTypeGuess p (SingleType t) Contravariant]-    filterToGuess p (TypeFilter FilterAllows t) =-      [InferredTypeGuess p (SingleType t) Covariant]+    filterToGuess p (TypeFilter FilterRequires t)+      | hasInferredParams (SingleType t) = []+      | otherwise = [InferredTypeGuess p (SingleType t) Contravariant]+    filterToGuess p (TypeFilter FilterAllows t)+      | hasInferredParams (SingleType t) = []+      | otherwise = [InferredTypeGuess p (SingleType t) Covariant]     filterToGuess _ _ = []  mergeInferredTypes :: (MergeableM m, CompileErrorM m, TypeResolver r) =>   r -> ParamFilters -> MergeTree InferredTypeGuess -> m [InferredTypeGuess] mergeInferredTypes r f = reduceMergeTree anyOp allOp leafOp where-  leafOp i = noInferred (itgGuess i) >> return [i]+  leafOp i = noInferred i >> return [i]   anyOp = mergeCommon anyCheck   allOp = mergeCommon allCheck   mergeCommon check is = do@@ -1000,10 +1031,9 @@          [i2] -> return [i2]          is2  -> compileErrorM $ "Could not reconcile guesses for " ++ show i ++                                  ": " ++ show is2-  noInferred (TypeMerge _ ts) = mergeAllM $ map noInferred ts-  noInferred (SingleType (JustTypeInstance (TypeInstance _ (Positional ts)))) = mergeAllM $ map noInferred ts-  noInferred (SingleType (JustInferredType i)) = compileErrorM $ "Failed to infer " ++ show i-  noInferred _ = return ()+  noInferred (InferredTypeGuess n t _) =+    when (hasInferredParams t) $+      compileErrorM $ "Guess " ++ show t ++ " for parameter " ++ show n ++ " contains inferred types"   anyCheck (InferredTypeGuess _ g1 v1) (InferredTypeGuess _ g2 _) =     -- Find the least-general guess: If g1 can be replaced with g2, prefer g1.     noInferredTypes $ checkGeneralMatch r f v1 g1 g2
src/Types/TypeInstance.hs view
@@ -31,6 +31,7 @@   InstanceParams,   InstanceVariances,   ParamFilters,+  ParamValues,   ParamVariances,   ParamName(..),   StorageType(..),@@ -43,11 +44,9 @@   checkGeneralMatch,   checkValueTypeMatch,   checkValueTypeMatch_,-  uncheckedSubFilter,-  uncheckedSubFilters,-  uncheckedSubInstance,-  uncheckedSubValueType,+  fixTypeParams,   getValueForParam,+  hasInferredParams,   isBuiltinCategory,   isDefinesFilter,   isRequiresFilter,@@ -55,6 +54,11 @@   noInferredTypes,   requiredParam,   requiredSingleton,+  uncheckedSubFilter,+  uncheckedSubFilters,+  uncheckedSubInstance,+  uncheckedSubValueType,+  unfixTypeParams,   validateAssignment,   validateDefinesInstance,   validateDefinesVariance,@@ -110,7 +114,7 @@ requiredSingleton n = ValueType RequiredValue $ SingleType $ JustTypeInstance $ TypeInstance n (Positional [])  requiredParam :: ParamName -> ValueType-requiredParam n = ValueType RequiredValue $ SingleType $ JustParamName n+requiredParam n = ValueType RequiredValue $ SingleType $ JustParamName False n  data CategoryName =   CategoryName {@@ -192,6 +196,7 @@     jtiType :: TypeInstance   } |   JustParamName {+    jpnFixed :: Bool,     jpnName :: ParamName   } |   JustInferredType {@@ -200,9 +205,10 @@   deriving (Eq,Ord)  instance Show TypeInstanceOrParam where-  show (JustTypeInstance t) = show t-  show (JustParamName n)    = show n-  show (JustInferredType i) = show i ++ " /*inferred*/"+  show (JustTypeInstance t)   = show t+  show (JustParamName True n) = show n ++ "/*fixed*/"+  show (JustParamName _ n)    = show n+  show (JustInferredType n)   = show n ++ "/*inferred*/"  data FilterDirection =   FilterRequires |@@ -239,12 +245,21 @@ viewTypeFilter :: ParamName -> TypeFilter -> String viewTypeFilter n f = show n ++ " " ++ show f +hasInferredParams :: GeneralInstance -> Bool+hasInferredParams (TypeMerge _ ts) =+  any hasInferredParams ts+hasInferredParams (SingleType (JustTypeInstance (TypeInstance _ (Positional ts)))) =+  any hasInferredParams ts+hasInferredParams (SingleType (JustInferredType _)) = True+hasInferredParams _                                 = False+ type InstanceParams = Positional GeneralInstance type InstanceVariances = Positional Variance type InstanceFilters = Positional [TypeFilter] -type ParamFilters = Map.Map ParamName [TypeFilter]+type ParamFilters   = Map.Map ParamName [TypeFilter] type ParamVariances = Map.Map ParamName Variance+type ParamValues    = Map.Map ParamName GeneralInstance  class TypeResolver r where   -- Performs parameter substitution for refines.@@ -283,12 +298,26 @@   resolve _        = compileErrorM $ "Param " ++ show n ++ " not found"  getValueForParam :: (CompileErrorM m) =>-  Map.Map ParamName GeneralInstance -> ParamName -> m GeneralInstance+  ParamValues -> ParamName -> m GeneralInstance getValueForParam pa n =   case n `Map.lookup` pa of-        (Just x) -> return x-        _ -> compileErrorM $ "Param " ++ show n ++ " does not exist"+       (Just x) -> return x+       _ -> compileErrorM $ "Param " ++ show n ++ " does not exist" +fixTypeParams :: GeneralInstance -> GeneralInstance+fixTypeParams = setParamsFixed True++unfixTypeParams :: GeneralInstance -> GeneralInstance+unfixTypeParams = setParamsFixed False++setParamsFixed :: Bool -> GeneralInstance -> GeneralInstance+setParamsFixed f (TypeMerge m ts) = TypeMerge m $ map (setParamsFixed f) ts+setParamsFixed f (SingleType (JustTypeInstance (TypeInstance t ts))) =+  SingleType $ JustTypeInstance $ TypeInstance t $ fmap (setParamsFixed f) ts+setParamsFixed f (SingleType (JustParamName _ n2)) =+  SingleType $ JustParamName f n2+setParamsFixed _ t = t+ noInferredTypes :: (MergeableM m, CompileErrorM m) => m (MergeTree InferredTypeGuess) -> m () noInferredTypes = id >=> reduceMergeTree return return message where   message i = compileErrorM $ "Type guess " ++ show i ++ " not allowed here"@@ -308,9 +337,8 @@ checkGeneralMatch :: (MergeableM m, CompileErrorM m, TypeResolver r) =>   r -> ParamFilters -> Variance ->   GeneralInstance -> GeneralInstance -> m (MergeTree InferredTypeGuess)-checkGeneralMatch r f v (SingleType (JustInferredType p1)) t2 = do-  compileWarningM $ "Treating inferred parameter " ++ show p1 ++ " on the left as a regular parameter"-  checkGeneralMatch r f v (SingleType $ JustParamName p1) t2+checkGeneralMatch _ _ _ (SingleType (JustInferredType p1)) _ =+  compileErrorM $ "Inferred parameter " ++ show p1 ++ " is not allowed on the left" checkGeneralMatch _ _ v t1 (SingleType (JustInferredType p2)) =   return $ mergeLeaf $ InferredTypeGuess p2 t1 v checkGeneralMatch r f Invariant ts1 ts2 =@@ -327,18 +355,17 @@ checkSingleMatch :: (MergeableM m, CompileErrorM m, TypeResolver r) =>   r -> ParamFilters -> Variance ->   TypeInstanceOrParam -> TypeInstanceOrParam -> m (MergeTree InferredTypeGuess)-checkSingleMatch r f v (JustInferredType p1) t2 = do-  compileWarningM $ "Treating inferred parameter " ++ show p1 ++ " on the left as a regular parameter"-  checkSingleMatch r f v (JustParamName p1) t2+checkSingleMatch _ _ _ (JustInferredType p1) _ =+  compileErrorM $ "Inferred parameter " ++ show p1 ++ " is not allowed on the left" checkSingleMatch _ _ v t1 (JustInferredType p2) =   return $ mergeLeaf $ InferredTypeGuess p2 (SingleType t1) v checkSingleMatch r f v (JustTypeInstance t1) (JustTypeInstance t2) =   checkInstanceToInstance r f v t1 t2-checkSingleMatch r f v (JustParamName p1) (JustTypeInstance t2) =+checkSingleMatch r f v (JustParamName _ p1) (JustTypeInstance t2) =   checkParamToInstance r f v p1 t2-checkSingleMatch r f v (JustTypeInstance t1) (JustParamName p2) =+checkSingleMatch r f v (JustTypeInstance t1) (JustParamName _ p2) =   checkInstanceToParam r f v t1 p2-checkSingleMatch r f v (JustParamName p1) (JustParamName p2) =+checkSingleMatch r f v (JustParamName _ p1) (JustParamName _ p2) =   checkParamToParam r f v p1 p2  checkInstanceToInstance :: (MergeableM m, CompileErrorM m, TypeResolver r) =>@@ -451,14 +478,16 @@     mergeAnyM (map (\(c1,c2) -> checkConstraintToConstraint v c1 c2) typeFilters) `reviseErrorM`       ("No filters imply " ++ show n1 ++ " -> " ++ show n2)     where+      selfParam1 = JustParamName False n1+      selfParam2 = JustParamName False n2       self1-        | v == Covariant = TypeFilter FilterRequires (JustParamName n1)-        | otherwise      = TypeFilter FilterAllows   (JustParamName n1)+        | v == Covariant = TypeFilter FilterRequires selfParam1+        | otherwise      = TypeFilter FilterAllows   selfParam1       self2-        | v == Covariant = TypeFilter FilterAllows   (JustParamName n2)-        | otherwise      = TypeFilter FilterRequires (JustParamName n2)+        | v == Covariant = TypeFilter FilterAllows   selfParam2+        | otherwise      = TypeFilter FilterRequires selfParam2       checkConstraintToConstraint Covariant (TypeFilter FilterRequires t1) (TypeFilter FilterAllows t2)-        | t1 == (JustParamName n1) && t2 == (JustParamName n2) =+        | t1 == selfParam1 && t2 == selfParam2 =           compileErrorM $ "Infinite recursion in " ++ show n1 ++ " -> " ++ show n2         -- x -> F1, F2 -> y implies x -> y only if F1 -> F2         | otherwise = checkSingleMatch r f Covariant t1 t2@@ -470,7 +499,7 @@                         viewTypeFilter n2 f2 ++ " do not imply " ++                         show n1 ++ " -> " ++ show n2       checkConstraintToConstraint Contravariant (TypeFilter FilterAllows t1) (TypeFilter FilterRequires t2)-        | t1 == (JustParamName n1) && t2 == (JustParamName n2) =+        | t1 == selfParam1 && t2 == selfParam2 =           compileErrorM $ "Infinite recursion in " ++ show n1 ++ " <- " ++ show n2         -- x <- F1, F2 <- y implies x <- y only if F1 <- F2         | otherwise = checkSingleMatch r f Contravariant t1 t2@@ -490,7 +519,7 @@   | otherwise      = mergeAllM (map (validateGeneralInstance r f) ts) validateGeneralInstance r f (SingleType (JustTypeInstance t)) =   validateTypeInstance r f t-validateGeneralInstance _ f (SingleType (JustParamName n)) =+validateGeneralInstance _ f (SingleType (JustParamName _ n)) =   when (not $ n `Map.member` f) $     compileErrorM $ "Param " ++ show n ++ " does not exist" validateGeneralInstance _ _ t = compileErrorM $ "Type " ++ show t ++ " contains unresolved types"@@ -531,7 +560,7 @@   checkDefinesFilter f2@(DefinesInstance n2 _) (JustTypeInstance t1) = do     ps1' <- trDefines r t1 n2     checkDefinesMatch r f f2 (DefinesInstance n2 ps1')-  checkDefinesFilter f2 (JustParamName n1) = do+  checkDefinesFilter f2 (JustParamName _ n1) = do       fs1 <- fmap (map dfType . filter isDefinesFilter) $ f `filterLookup` n1       mergeAnyM (map (checkDefinesMatch r f f2) fs1) `reviseErrorM`         ("No filters imply " ++ show n1 ++ " defines " ++ show f2)@@ -556,7 +585,7 @@   mergeAllM (map (validateInstanceVariance r vm v) ts) validateInstanceVariance r vm v (TypeMerge MergeIntersect ts) =   mergeAllM (map (validateInstanceVariance r vm v) ts)-validateInstanceVariance _ vm v (SingleType (JustParamName n)) =+validateInstanceVariance _ vm v (SingleType (JustParamName _ n)) =   case n `Map.lookup` vm of       Nothing -> compileErrorM $ "Param " ++ show n ++ " is undefined"       (Just v0) -> when (not $ v0 `paramAllowsVariance` v) $@@ -590,7 +619,8 @@     gs <- mapErrorsM subAll ts     let t2 = SingleType $ JustTypeInstance $ TypeInstance n (Positional gs)     return (t2)-  subInstance (JustParamName n) = replace n+  subInstance p@(JustParamName True _) = return $ SingleType p+  subInstance (JustParamName _ n)      = replace n   subInstance t = compileErrorM $ "Type " ++ show t ++ " contains unresolved types"  uncheckedSubFilter :: (MergeableM m, CompileErrorM m) =>
tests/inference.0rt view
@@ -194,7 +194,7 @@  testcase "inference from filter" {   error-  require "Formatted"+  require "#x.+get.+Formatted"   require "String"   require "value2"   exclude "value1"@@ -210,6 +210,93 @@     #x allows Formatted   (#x) -> (#x)   get (x) {+    return x+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "inference from filter without param" {+  error+  require "#x.+get.+Formatted"+  require "String"+  require "value2"+  exclude "value1"+}++define Test {+  run () {+    Formatted value1 <- get<Formatted,?>("value")+    String    value2 <- get<Formatted,?>("value")+  }++  @type get<#y,#x>+    #x allows #y+  (#x) -> (#x)+  get (x) {+    return x+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "inference from filter including param" {+  error+  require "#x.+get.+Type<String>"+}++concrete Type<#x> {+  @type create () -> (Type<#x>)+}++define Type {+  create () {+    return Type<#x>{ }+  }+}++define Test {+  run () {+    Type<String> value2 <- get<?>(Type<String>$create())+  }++  @type get<#x>+    #x allows Type<#x>+  (#x) -> (#x)+  get (x) {+    return x+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "clashing param filter in the same scope" {+  success Test$run()+}++define Test {+  run () {+    \ get1<Int>()+  }++  @type get1<#x>+    #x requires Int+  () -> ()+  get1 () {+    String value <- get2<?>("message")+  }++  @type get2<#x> (#x) -> (#x)+  get2 (x) {     return x   } }
+ tests/regressions.0rt view
@@ -0,0 +1,52 @@+/* -----------------------------------------------------------------------------+Copyright 2020 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++testcase "Issue #73 is fixed" {+  success empty+}++concrete Type1<#x> {+  @type call<#y> (#x) -> ()+}++define Type1 {+  call (_) {}+}++concrete Type2<#y> {+  @type call () -> ()+}++define Type2 {+  call () {+    // Value<#y> gets subbed in for #x, so call is re-parameterized with an+    // argument of type Value<#y>. When the compiler processes call<Int>, it+    // looks for #y, which it finds; however, it's a different #y.+    \ Type1<Value<#y>>$call<Int>(Value<#y>$create())+  }+}++concrete Value<#z> {+  @type create () -> (Value<#z>)+}++define Value {+  create () {+    return Value<#z>{ }+  }+}
zeolite-lang.cabal view
@@ -1,7 +1,7 @@ cabal-version:       2.2  name:                zeolite-lang-version:             0.7.0.0+version:             0.7.0.1 synopsis:            Zeolite is a statically-typed, general-purpose programming language.  description: