packages feed

zeolite-lang 0.9.0.0 → 0.10.0.0

raw patch · 105 files changed

+4413/−5338 lines, 105 filesdep +parser-combinatorsPVP ok

version bump matches the API change (PVP)

Dependencies added: parser-combinators

API changes (from Hackage documentation)

- CompilerCxx.Category: compileTestMain :: (Show c, CompileErrorM m) => LanguageModule c -> PrivateSource c -> Expression c -> m CxxOutput
- Parser.DefinedCategory: parseAnySource :: Parser ([AnyCategory SourcePos], [DefinedCategory SourcePos])
- Parser.Pragma: parseMacroName :: Parser String
- Types.IntegrationTest: [ereExpression] :: ExpectedResult c -> Expression c
- Types.IntegrationTest: [ersExpression] :: ExpectedResult c -> Expression c
- Types.TypeCategory: instance GHC.Show.Show a => GHC.Show.Show (Types.TypeCategory.GuessRange a)
+ Base.CompileError: infixl 1 <!!
+ Base.CompileError: infixr 1 !!>
+ Base.Mergeable: (<&&>) :: Mergeable a => a -> a -> a
+ Base.Mergeable: (<||>) :: Mergeable a => a -> a -> a
+ Base.Mergeable: infixl 2 <&&>
+ Cli.Programs: [tcArgs] :: TestCommand -> [String]
+ Compilation.CompilerState: ccReleaseExprMacro :: CompilerContext c m s a => a -> [c] -> MacroName -> m a
+ Compilation.CompilerState: ccReserveExprMacro :: CompilerContext c m s a => a -> [c] -> MacroName -> m a
+ Compilation.CompilerState: csReleaseExprMacro :: CompilerContext c m s a => [c] -> MacroName -> CompilerState a m ()
+ Compilation.CompilerState: csReserveExprMacro :: CompilerContext c m s a => [c] -> MacroName -> CompilerState a m ()
+ Compilation.CompilerState: infixl 1 <!!!
+ Compilation.CompilerState: infixr 1 !!!>
+ Compilation.ProcedureContext: [pcReservedMacros] :: ProcedureContext c -> [(MacroName, [c])]
+ CompilerCxx.Category: compileTestsModule :: (Show c, CompileErrorM m) => LanguageModule c -> Namespace -> [String] -> [AnyCategory c] -> [DefinedCategory c] -> [TestProcedure c] -> m ([CxxOutput], CxxOutput, [(FunctionName, [c])])
+ CompilerCxx.Code: startInitTracing :: CategoryName -> SymbolScope -> String
+ CompilerCxx.Code: startTestTracing :: FunctionName -> String
+ CompilerCxx.Naming: testFunctionName :: FunctionName -> String
+ CompilerCxx.Procedure: compileTestProcedure :: (Show c, CompileErrorM m) => CategoryMap c -> ExprMap c -> TestProcedure c -> m (CompiledData [String])
+ CompilerCxx.Procedure: selectTestFromArgv1 :: CompileErrorM m => [FunctionName] -> m ([String], CompiledData [String])
+ Parser.Common: kwUnittest :: Monad m => ParserE m ()
+ Parser.Common: parseAny2 :: Monad m => ParserE m a -> ParserE m b -> ParserE m ([a], [b])
+ Parser.Common: parseAny3 :: Monad m => ParserE m a -> ParserE m b -> ParserE m c -> ParserE m ([a], [b], [c])
+ Parser.Common: parseErrorM :: CompileErrorM m => SourcePos -> String -> ParserE m a
+ Parser.Common: quotedString :: Monad m => ParserE m String
+ Parser.Common: runParserE :: CompileErrorM m => ParserE m a -> String -> String -> m a
+ Parser.Common: type ParserE = ParsecT String ()
+ Parser.Pragma: instance Parser.Common.ParseFromSource Types.Pragma.MacroName
+ Parser.Procedure: instance Parser.Common.ParseFromSource (Types.Procedure.TestProcedure Text.Parsec.Pos.SourcePos)
+ Types.IntegrationTest: ExpectCompiles :: [c] -> [OutputPattern] -> [OutputPattern] -> ExpectedResult c
+ Types.IntegrationTest: [itTests] :: IntegrationTest c -> [TestProcedure c]
+ Types.IntegrationTest: [ithArgs] :: IntegrationTestHeader c -> [String]
+ Types.IntegrationTest: isExpectCompiles :: ExpectedResult c -> Bool
+ Types.Pragma: MacroName :: String -> MacroName
+ Types.Pragma: [mnName] :: MacroName -> String
+ Types.Pragma: instance GHC.Classes.Eq Types.Pragma.MacroName
+ Types.Pragma: instance GHC.Classes.Ord Types.Pragma.MacroName
+ Types.Pragma: instance GHC.Show.Show Types.Pragma.MacroName
+ Types.Pragma: newtype MacroName
+ Types.Procedure: TestProcedure :: [c] -> FunctionName -> Procedure c -> TestProcedure c
+ Types.Procedure: [tpContext] :: TestProcedure c -> [c]
+ Types.Procedure: [tpName] :: TestProcedure c -> FunctionName
+ Types.Procedure: [tpProcedure] :: TestProcedure c -> Procedure c
+ Types.Procedure: data TestProcedure c
+ Types.Procedure: instance GHC.Show.Show c => GHC.Show.Show (Types.Procedure.TestProcedure c)
+ Types.TypeCategory: instance (GHC.Enum.Bounded a, GHC.Classes.Eq a, GHC.Show.Show a) => GHC.Show.Show (Types.TypeCategory.GuessRange a)
- Base.CompileInfo: type CompileInfo a = CompileInfoT Identity a
+ Base.CompileInfo: type CompileInfo = CompileInfoT Identity
- Base.CompileInfo: type CompileInfoIO a = CompileInfoT IO a
+ Base.CompileInfo: type CompileInfoIO = CompileInfoT IO
- Cli.Programs: TestCommand :: String -> String -> TestCommand
+ Cli.Programs: TestCommand :: String -> String -> [String] -> TestCommand
- Compilation.CompilerState: ccExprLookup :: CompilerContext c m s a => a -> [c] -> String -> m (Expression c)
+ Compilation.CompilerState: ccExprLookup :: CompilerContext c m s a => a -> [c] -> MacroName -> m (Expression c)
- Compilation.CompilerState: csExprLookup :: CompilerContext c m s a => [c] -> String -> CompilerState a m (Expression c)
+ Compilation.CompilerState: csExprLookup :: CompilerContext c m s a => [c] -> MacroName -> CompilerState a m (Expression c)
- Compilation.ProcedureContext: ProcedureContext :: SymbolScope -> CategoryName -> Positional (ValueParam c) -> Positional (ValueParam c) -> [DefinedMember c] -> CategoryMap c -> ParamFilters -> [ParamFilter c] -> [ParamFilter c] -> Map ParamName SymbolScope -> Map FunctionName (ScopedFunction c) -> Map VariableName (VariableValue c) -> ReturnValidation c -> JumpType -> Bool -> [ReturnVariable] -> Set CategoryName -> [String] -> Bool -> LoopSetup [String] -> [CleanupSetup (ProcedureContext c) [String]] -> Bool -> ExprMap c -> Bool -> ProcedureContext c
+ Compilation.ProcedureContext: ProcedureContext :: SymbolScope -> CategoryName -> Positional (ValueParam c) -> Positional (ValueParam c) -> [DefinedMember c] -> CategoryMap c -> ParamFilters -> [ParamFilter c] -> [ParamFilter c] -> Map ParamName SymbolScope -> Map FunctionName (ScopedFunction c) -> Map VariableName (VariableValue c) -> ReturnValidation c -> JumpType -> Bool -> [ReturnVariable] -> Set CategoryName -> [String] -> Bool -> LoopSetup [String] -> [CleanupSetup (ProcedureContext c) [String]] -> Bool -> ExprMap c -> [(MacroName, [c])] -> Bool -> ProcedureContext c
- Compilation.ProcedureContext: type ExprMap c = Map String (Expression c)
+ Compilation.ProcedureContext: type ExprMap c = Map MacroName (Expression c)
- CompilerCxx.Category: CxxOutput :: Maybe CategoryName -> String -> Namespace -> [Namespace] -> [CategoryName] -> [String] -> CxxOutput
+ CompilerCxx.Category: CxxOutput :: Maybe CategoryName -> String -> Namespace -> Set Namespace -> Set CategoryName -> [String] -> CxxOutput
- CompilerCxx.Category: LanguageModule :: [Namespace] -> [Namespace] -> [Namespace] -> [AnyCategory c] -> [AnyCategory c] -> [AnyCategory c] -> [AnyCategory c] -> [AnyCategory c] -> [AnyCategory c] -> [CategoryName] -> [CategoryName] -> ExprMap c -> LanguageModule c
+ CompilerCxx.Category: LanguageModule :: Set Namespace -> Set Namespace -> Set Namespace -> [AnyCategory c] -> [AnyCategory c] -> [AnyCategory c] -> [AnyCategory c] -> [AnyCategory c] -> [AnyCategory c] -> [CategoryName] -> [CategoryName] -> ExprMap c -> LanguageModule c
- CompilerCxx.Category: [coUsesCategory] :: CxxOutput -> [CategoryName]
+ CompilerCxx.Category: [coUsesCategory] :: CxxOutput -> Set CategoryName
- CompilerCxx.Category: [coUsesNamespace] :: CxxOutput -> [Namespace]
+ CompilerCxx.Category: [coUsesNamespace] :: CxxOutput -> Set Namespace
- CompilerCxx.Category: [lmLocalNamespaces] :: LanguageModule c -> [Namespace]
+ CompilerCxx.Category: [lmLocalNamespaces] :: LanguageModule c -> Set Namespace
- CompilerCxx.Category: [lmPrivateNamespaces] :: LanguageModule c -> [Namespace]
+ CompilerCxx.Category: [lmPrivateNamespaces] :: LanguageModule c -> Set Namespace
- CompilerCxx.Category: [lmPublicNamespaces] :: LanguageModule c -> [Namespace]
+ CompilerCxx.Category: [lmPublicNamespaces] :: LanguageModule c -> Set Namespace
- CompilerCxx.Category: compileCategoryDeclaration :: (Show c, CompileErrorM m) => Bool -> CategoryMap c -> [Namespace] -> AnyCategory c -> m CxxOutput
+ CompilerCxx.Category: compileCategoryDeclaration :: (Show c, CompileErrorM m) => Bool -> CategoryMap c -> Set Namespace -> AnyCategory c -> m CxxOutput
- CompilerCxx.Category: compileConcreteDefinition :: (Show c, CompileErrorM m) => Bool -> CategoryMap c -> ExprMap c -> [Namespace] -> Maybe [ValueRefine c] -> DefinedCategory c -> m CxxOutput
+ CompilerCxx.Category: compileConcreteDefinition :: (Show c, CompileErrorM m) => Bool -> CategoryMap c -> ExprMap c -> Set Namespace -> Maybe [ValueRefine c] -> DefinedCategory c -> m CxxOutput
- CompilerCxx.Code: startFunctionTracing :: String -> String
+ CompilerCxx.Code: startFunctionTracing :: CategoryName -> FunctionName -> String
- Module.CompileMetadata: ModuleConfig :: FilePath -> FilePath -> [(String, Expression SourcePos)] -> [FilePath] -> [FilePath] -> [ExtraSource] -> [FilePath] -> CompileMode -> ModuleConfig
+ Module.CompileMetadata: ModuleConfig :: FilePath -> FilePath -> [(MacroName, Expression SourcePos)] -> [FilePath] -> [FilePath] -> [ExtraSource] -> [FilePath] -> CompileMode -> ModuleConfig
- Module.CompileMetadata: [mcExprMap] :: ModuleConfig -> [(String, Expression SourcePos)]
+ Module.CompileMetadata: [mcExprMap] :: ModuleConfig -> [(MacroName, Expression SourcePos)]
- Module.ProcessMetadata: getObjectFileResolver :: [ObjectFile] -> [Namespace] -> [CategoryName] -> [FilePath]
+ Module.ProcessMetadata: getObjectFileResolver :: [ObjectFile] -> Set Namespace -> Set CategoryName -> [FilePath]
- Parser.Common: anyComment :: Parser String
+ Parser.Common: anyComment :: Monad m => ParserE m String
- Parser.Common: assignOperator :: Parser ()
+ Parser.Common: assignOperator :: Monad m => ParserE m ()
- Parser.Common: blockComment :: Parser String
+ Parser.Common: blockComment :: Monad m => ParserE m String
- Parser.Common: builtinValues :: Parser String
+ Parser.Common: builtinValues :: Monad m => ParserE m String
- Parser.Common: categorySymbolGet :: Parser ()
+ Parser.Common: categorySymbolGet :: CompileErrorM m => ParserE m ()
- Parser.Common: char_ :: Char -> Parser ()
+ Parser.Common: char_ :: Monad m => Char -> ParserE m ()
- Parser.Common: endOfDoc :: Parser ()
+ Parser.Common: endOfDoc :: Monad m => ParserE m ()
- Parser.Common: escapeStart :: Parser ()
+ Parser.Common: escapeStart :: Monad m => ParserE m ()
- Parser.Common: inferredParam :: Parser ()
+ Parser.Common: inferredParam :: Monad m => ParserE m ()
- Parser.Common: infixFuncEnd :: Parser ()
+ Parser.Common: infixFuncEnd :: Monad m => ParserE m ()
- Parser.Common: infixFuncStart :: Parser ()
+ Parser.Common: infixFuncStart :: Monad m => ParserE m ()
- Parser.Common: keyword :: String -> Parser ()
+ Parser.Common: keyword :: Monad m => String -> ParserE m ()
- Parser.Common: kwAll :: Parser ()
+ Parser.Common: kwAll :: Monad m => ParserE m ()
- Parser.Common: kwAllows :: Parser ()
+ Parser.Common: kwAllows :: Monad m => ParserE m ()
- Parser.Common: kwAny :: Parser ()
+ Parser.Common: kwAny :: Monad m => ParserE m ()
- Parser.Common: kwBreak :: Parser ()
+ Parser.Common: kwBreak :: Monad m => ParserE m ()
- Parser.Common: kwCategory :: Parser ()
+ Parser.Common: kwCategory :: Monad m => ParserE m ()
- Parser.Common: kwCleanup :: Parser ()
+ Parser.Common: kwCleanup :: Monad m => ParserE m ()
- Parser.Common: kwConcrete :: Parser ()
+ Parser.Common: kwConcrete :: Monad m => ParserE m ()
- Parser.Common: kwContinue :: Parser ()
+ Parser.Common: kwContinue :: Monad m => ParserE m ()
- Parser.Common: kwDefine :: Parser ()
+ Parser.Common: kwDefine :: Monad m => ParserE m ()
- Parser.Common: kwDefines :: Parser ()
+ Parser.Common: kwDefines :: Monad m => ParserE m ()
- Parser.Common: kwElif :: Parser ()
+ Parser.Common: kwElif :: Monad m => ParserE m ()
- Parser.Common: kwElse :: Parser ()
+ Parser.Common: kwElse :: Monad m => ParserE m ()
- Parser.Common: kwEmpty :: Parser ()
+ Parser.Common: kwEmpty :: Monad m => ParserE m ()
- Parser.Common: kwFail :: Parser ()
+ Parser.Common: kwFail :: Monad m => ParserE m ()
- Parser.Common: kwFalse :: Parser ()
+ Parser.Common: kwFalse :: Monad m => ParserE m ()
- Parser.Common: kwIf :: Parser ()
+ Parser.Common: kwIf :: Monad m => ParserE m ()
- Parser.Common: kwIgnore :: Parser ()
+ Parser.Common: kwIgnore :: Monad m => ParserE m ()
- Parser.Common: kwIn :: Parser ()
+ Parser.Common: kwIn :: Monad m => ParserE m ()
- Parser.Common: kwInterface :: Parser ()
+ Parser.Common: kwInterface :: Monad m => ParserE m ()
- Parser.Common: kwOptional :: Parser ()
+ Parser.Common: kwOptional :: Monad m => ParserE m ()
- Parser.Common: kwPresent :: Parser ()
+ Parser.Common: kwPresent :: Monad m => ParserE m ()
- Parser.Common: kwReduce :: Parser ()
+ Parser.Common: kwReduce :: Monad m => ParserE m ()
- Parser.Common: kwRefines :: Parser ()
+ Parser.Common: kwRefines :: Monad m => ParserE m ()
- Parser.Common: kwRequire :: Parser ()
+ Parser.Common: kwRequire :: Monad m => ParserE m ()
- Parser.Common: kwRequires :: Parser ()
+ Parser.Common: kwRequires :: Monad m => ParserE m ()
- Parser.Common: kwReturn :: Parser ()
+ Parser.Common: kwReturn :: Monad m => ParserE m ()
- Parser.Common: kwScoped :: Parser ()
+ Parser.Common: kwScoped :: Monad m => ParserE m ()
- Parser.Common: kwSelf :: Parser ()
+ Parser.Common: kwSelf :: Monad m => ParserE m ()
- Parser.Common: kwStrong :: Parser ()
+ Parser.Common: kwStrong :: Monad m => ParserE m ()
- Parser.Common: kwTestcase :: Parser ()
+ Parser.Common: kwTestcase :: Monad m => ParserE m ()
- Parser.Common: kwTrue :: Parser ()
+ Parser.Common: kwTrue :: Monad m => ParserE m ()
- Parser.Common: kwType :: Parser ()
+ Parser.Common: kwType :: Monad m => ParserE m ()
- Parser.Common: kwTypename :: Parser ()
+ Parser.Common: kwTypename :: Monad m => ParserE m ()
- Parser.Common: kwTypes :: Parser ()
+ Parser.Common: kwTypes :: Monad m => ParserE m ()
- Parser.Common: kwUpdate :: Parser ()
+ Parser.Common: kwUpdate :: Monad m => ParserE m ()
- Parser.Common: kwValue :: Parser ()
+ Parser.Common: kwValue :: Monad m => ParserE m ()
- Parser.Common: kwWeak :: Parser ()
+ Parser.Common: kwWeak :: Monad m => ParserE m ()
- Parser.Common: kwWhile :: Parser ()
+ Parser.Common: kwWhile :: Monad m => ParserE m ()
- Parser.Common: labeled :: String -> Parser a -> Parser a
+ Parser.Common: labeled :: Monad m => String -> ParserE m a -> ParserE m a
- Parser.Common: lineComment :: Parser String
+ Parser.Common: lineComment :: Monad m => ParserE m String
- Parser.Common: lineEnd :: Parser ()
+ Parser.Common: lineEnd :: Monad m => ParserE m ()
- Parser.Common: noKeywords :: Parser ()
+ Parser.Common: noKeywords :: Monad m => ParserE m ()
- Parser.Common: notAllowed :: Parser a -> String -> Parser ()
+ Parser.Common: notAllowed :: ParserE m a -> String -> ParserE m ()
- Parser.Common: nullParse :: Parser ()
+ Parser.Common: nullParse :: Monad m => ParserE m ()
- Parser.Common: operator :: String -> Parser String
+ Parser.Common: operator :: Monad m => String -> ParserE m String
- Parser.Common: optionalSpace :: Parser ()
+ Parser.Common: optionalSpace :: Monad m => ParserE m ()
- Parser.Common: parseBin :: Parser Integer
+ Parser.Common: parseBin :: Monad m => ParserE m Integer
- Parser.Common: parseDec :: Parser Integer
+ Parser.Common: parseDec :: Monad m => ParserE m Integer
- Parser.Common: parseHex :: Parser Integer
+ Parser.Common: parseHex :: Monad m => ParserE m Integer
- Parser.Common: parseOct :: Parser Integer
+ Parser.Common: parseOct :: Monad m => ParserE m Integer
- Parser.Common: parseSubOne :: Parser (Integer, Integer)
+ Parser.Common: parseSubOne :: Monad m => ParserE m (Integer, Integer)
- Parser.Common: pragmaArgsEnd :: Parser ()
+ Parser.Common: pragmaArgsEnd :: Monad m => ParserE m ()
- Parser.Common: pragmaArgsStart :: Parser ()
+ Parser.Common: pragmaArgsStart :: Monad m => ParserE m ()
- Parser.Common: pragmaEnd :: Parser ()
+ Parser.Common: pragmaEnd :: Monad m => ParserE m ()
- Parser.Common: pragmaStart :: Parser ()
+ Parser.Common: pragmaStart :: Monad m => ParserE m ()
- Parser.Common: regexChar :: Parser String
+ Parser.Common: regexChar :: Monad m => ParserE m String
- Parser.Common: requiredSpace :: Parser ()
+ Parser.Common: requiredSpace :: Monad m => ParserE m ()
- Parser.Common: sepAfter :: Parser a -> Parser a
+ Parser.Common: sepAfter :: Monad m => ParserE m a -> ParserE m a
- Parser.Common: sepAfter1 :: Parser a -> Parser a
+ Parser.Common: sepAfter1 :: Monad m => ParserE m a -> ParserE m a
- Parser.Common: sepAfter_ :: Parser a -> Parser ()
+ Parser.Common: sepAfter_ :: Monad m => ParserE m a -> ParserE m ()
- Parser.Common: sourceParser :: ParseFromSource a => Parser a
+ Parser.Common: sourceParser :: (ParseFromSource a, CompileErrorM m) => ParserE m a
- Parser.Common: statementEnd :: Parser ()
+ Parser.Common: statementEnd :: Monad m => ParserE m ()
- Parser.Common: statementStart :: Parser ()
+ Parser.Common: statementStart :: Monad m => ParserE m ()
- Parser.Common: stringChar :: Parser Char
+ Parser.Common: stringChar :: Monad m => ParserE m Char
- Parser.Common: string_ :: String -> Parser ()
+ Parser.Common: string_ :: Monad m => String -> ParserE m ()
- Parser.Common: typeSymbolGet :: Parser ()
+ Parser.Common: typeSymbolGet :: CompileErrorM m => ParserE m ()
- Parser.Common: valueSymbolGet :: Parser ()
+ Parser.Common: valueSymbolGet :: Monad m => ParserE m ()
- Parser.Pragma: parsePragmas :: [Parser a] -> Parser [a]
+ Parser.Pragma: parsePragmas :: CompileErrorM m => [ParserE m a] -> ParserE m [a]
- Parser.Pragma: pragmaComment :: Parser (Pragma SourcePos)
+ Parser.Pragma: pragmaComment :: CompileErrorM m => ParserE m (Pragma SourcePos)
- Parser.Pragma: pragmaExprLookup :: Parser (Pragma SourcePos)
+ Parser.Pragma: pragmaExprLookup :: CompileErrorM m => ParserE m (Pragma SourcePos)
- Parser.Pragma: pragmaModuleOnly :: Parser (Pragma SourcePos)
+ Parser.Pragma: pragmaModuleOnly :: CompileErrorM m => ParserE m (Pragma SourcePos)
- Parser.Pragma: pragmaNoTrace :: Parser (Pragma SourcePos)
+ Parser.Pragma: pragmaNoTrace :: CompileErrorM m => ParserE m (Pragma SourcePos)
- Parser.Pragma: pragmaSourceContext :: Parser (Pragma SourcePos)
+ Parser.Pragma: pragmaSourceContext :: CompileErrorM m => ParserE m (Pragma SourcePos)
- Parser.Pragma: pragmaTestsOnly :: Parser (Pragma SourcePos)
+ Parser.Pragma: pragmaTestsOnly :: CompileErrorM m => ParserE m (Pragma SourcePos)
- Parser.Pragma: pragmaTraceCreation :: Parser (Pragma SourcePos)
+ Parser.Pragma: pragmaTraceCreation :: CompileErrorM m => ParserE m (Pragma SourcePos)
- Parser.TypeCategory: parseFilters :: Parser [ParamFilter SourcePos]
+ Parser.TypeCategory: parseFilters :: CompileErrorM m => ParserE m [ParamFilter SourcePos]
- Parser.TypeCategory: parseScope :: Parser SymbolScope
+ Parser.TypeCategory: parseScope :: Monad m => ParserE m SymbolScope
- Parser.TypeCategory: parseScopedFunction :: Parser SymbolScope -> Parser CategoryName -> Parser (ScopedFunction SourcePos)
+ Parser.TypeCategory: parseScopedFunction :: CompileErrorM m => ParserE m SymbolScope -> ParserE m CategoryName -> ParserE m (ScopedFunction SourcePos)
- Parser.TypeCategory: singleDefine :: Parser (ValueDefine SourcePos)
+ Parser.TypeCategory: singleDefine :: CompileErrorM m => ParserE m (ValueDefine SourcePos)
- Parser.TypeCategory: singleFilter :: Parser (ParamFilter SourcePos)
+ Parser.TypeCategory: singleFilter :: CompileErrorM m => ParserE m (ParamFilter SourcePos)
- Parser.TypeCategory: singleRefine :: Parser (ValueRefine SourcePos)
+ Parser.TypeCategory: singleRefine :: CompileErrorM m => ParserE m (ValueRefine SourcePos)
- Test.Common: readSingleWith :: Parser a -> String -> String -> CompileInfo a
+ Test.Common: readSingleWith :: ParserE CompileInfo a -> String -> String -> CompileInfo a
- Types.IntegrationTest: ExpectRuntimeError :: [c] -> Expression c -> [OutputPattern] -> [OutputPattern] -> ExpectedResult c
+ Types.IntegrationTest: ExpectRuntimeError :: [c] -> [OutputPattern] -> [OutputPattern] -> ExpectedResult c
- Types.IntegrationTest: ExpectRuntimeSuccess :: [c] -> Expression c -> [OutputPattern] -> [OutputPattern] -> ExpectedResult c
+ Types.IntegrationTest: ExpectRuntimeSuccess :: [c] -> [OutputPattern] -> [OutputPattern] -> ExpectedResult c
- Types.IntegrationTest: IntegrationTest :: IntegrationTestHeader c -> [AnyCategory c] -> [DefinedCategory c] -> IntegrationTest c
+ Types.IntegrationTest: IntegrationTest :: IntegrationTestHeader c -> [AnyCategory c] -> [DefinedCategory c] -> [TestProcedure c] -> IntegrationTest c
- Types.IntegrationTest: IntegrationTestHeader :: [c] -> String -> ExpectedResult c -> IntegrationTestHeader c
+ Types.IntegrationTest: IntegrationTestHeader :: [c] -> String -> [String] -> ExpectedResult c -> IntegrationTestHeader c
- Types.Pragma: PragmaExprLookup :: [c] -> String -> Pragma c
+ Types.Pragma: PragmaExprLookup :: [c] -> MacroName -> Pragma c
- Types.Pragma: [pelName] :: Pragma c -> String
+ Types.Pragma: [pelName] :: Pragma c -> MacroName
- Types.Procedure: NamedMacro :: [c] -> String -> ExpressionStart c
+ Types.Procedure: NamedMacro :: [c] -> MacroName -> ExpressionStart c

Files

ChangeLog.md view
@@ -1,5 +1,75 @@ # Revision history for zeolite-lang +## 0.10.0.0  -- 2020-12-05++### Language++* **[breaking]** Major changes to `.0rt` syntax:++  * **[breaking]** Removes the expression argument from `success` and `crash`+    `testcase` types. Use one or more `unittest` (see next point) instead.++  * **[new]** Adds `unittest` keyword to allow the user to define multiple+    tests within a single `success` `testcase`.++    ```text+    testcase "simple tests" {+      success+    }++    unittest checkInvariant1 {+      // this is a regular procedure with no return+    }++    unittest checkInvariant2 {+      // this is a regular procedure with no return+    }+    ```++    This allows multiple tests to use the same setup, while still being able to+    track multiple test failures. `error` and `crash` `testcase` types are still+    available.++  * **[breaking]** Allows `testcase` to statically set `Argv` (see `lib/util`)+    using the `args` keyword. By default, only the program name is set.+    Previously, `Argv` used whatever was passed to the test binary.++    ```text+    testcase "with static Argv" {+      success+      args "arg1" "arg2"+    }++    unittest test {+      // something that requires Argv.global()+    }+    ```++    Note that this *isn't* a+    library change; this also affects C++ extensions that use `Argv` from+    `base/logging.hpp`.++  * **[new]** Adds `compiles` mode for `testcase`. This is like `success` except+    nothing is executed. (`success` requires at least one `unittest`, whereas+    `compiles` will not execute anything even if `unittest` are present.)++### Libraries++* **[new]** Adds the `lib/testing` library with basic helpers for unit tests.++### Compiler CLI++* **[new]** Updates parsing of `.zeolite-module` to allow any ordering of the+  fields. Previously, the fields needed to be in a very specific order.++* **[fix]** Adds compile-time protection against self-referential expression+  macros defined in `expression_map:` in `.zeolite-module`. Previously, the+  result was infinite recursion that could exhaust system resources.++* **[breaking]** Adds an error when `root`/`path` in `.zeolite-module` differs+  from the location of the respective `.zeolite-module`. This is to catch both+  typos (e.g., copy-and-paste errors) and ambiguities.+ ## 0.9.0.0  -- 2020-11-23  ### Compiler CLI
bin/unit-tests.hs view
@@ -48,4 +48,4 @@   ]  labelWith :: String -> [IO (CompileInfo ())] -> [IO (CompileInfo ())]-labelWith s ts = map (\(n,t) -> fmap (<?? ("In " ++ s ++ " (#" ++ show n ++ "):")) t) (zip ([1..] :: [Int]) ts)+labelWith s ts = map (\(n,t) -> fmap (<?? "In " ++ s ++ " (#" ++ show n ++ "):") t) (zip ([1..] :: [Int]) ts)
bin/zeolite-setup.hs view
@@ -22,9 +22,9 @@ import System.Exit import System.IO +import Base.CompileInfo import Cli.CompileOptions import Cli.RunCompiler-import Base.CompileInfo import Config.LoadConfig import Config.LocalConfig @@ -55,10 +55,11 @@ libraries :: [String] libraries = [     "base",-    "tests",+    "lib/testing",     "lib/util",     "lib/file",-    "lib/math"+    "lib/math",+    "tests"   ]  includePaths :: [String]
example/parser/parser-test.0rt view
@@ -1,29 +1,28 @@ testcase "parse data from a file" {-  success Test.execute()-}--concrete Test {-  @type execute () -> ()+  success } -define Test {-  execute () {-    TestData data <- TestData.parseFrom(loadTestData()).getValue()+unittest test {+  TestData data <- TestData.parseFrom(Helpers.loadTestData()).getValue() -    if (data.getName() != "example data") {-      fail(data.getName())-    }+  if (data.getName() != "example data") {+    fail(data.getName())+  } -    if (data.getDescription() != "THIS_IS_A_TOKEN") {-      fail(data.getDescription())-    }+  if (data.getDescription() != "THIS_IS_A_TOKEN") {+    fail(data.getDescription())+  } -    if (data.getBoolean() != false) {-      fail(data.getBoolean())-    }+  if (data.getBoolean() != false) {+    fail(data.getBoolean())   }+} +concrete Helpers {   @type loadTestData () -> (String)+}++define Helpers {   loadTestData () {     scoped {       RawFileReader reader <- RawFileReader.open($ExprLookup[MODULE_PATH]$ + "/test-data.txt")
example/tree/tree-test.0rt view
@@ -1,64 +1,62 @@ // Each testcase is essentially followed by its own private .0rx that is-// separate from all other testcases. In this case, the testcase expects that-// the source will compile and Test.execute() will succeed, but testcases can-// also expect a compiler error ("error") or a runtime crash ("crash"). Note-// that you *cannot* expect parse-time errors.+// separate from all other testcases. In addition to category declarations and+// definitions, each testcase can define one or more unittest procedures.+//+// In this example, "success" means that all unittest are expected to succeed.+// The other options are "crash" for a runtime failure and "error" for a+// compilation error.  testcase "integration test" {-  success Test.execute()+  success } -// Everything past the testcase (up until the next testcase, if there is one) is-// treated as a self-contained .0rx. This is compiled into a binary that calls-// the expression that follows "success" above.+// Everything past here until the next testcase belongs to this testcase. This+// allows you to perform additional setup. -concrete Test {-  @type execute () -> ()-}+// Each unittest is executed separately. If one unittest updates global state,+// it won't affect any other unittest. -define Test {-  execute () {-    // Just select the required usage patterns with an intersection.-    [KVWriter<Int,Int>&KVReader<Int,Int>] tree <- Tree<Int,Int>.new()-    Int count <- 30+unittest test {+  // Just select the required usage patterns with an intersection.+  [KVWriter<Int,Int>&KVReader<Int,Int>] tree <- Tree<Int,Int>.new()+  Int count <- 30 -    // Insert values.-    scoped {-      Int i <- 0-    } in while (i < count) {-      Int new <- ((i + 13) * 3547) % count-      \ tree.set(new,i)-    } update {-      i <- i+1-    }+  // Insert values.+  scoped {+    Int i <- 0+  } in while (i < count) {+    Int new <- ((i + 13) * 3547) % count+    \ tree.set(new,i)+  } update {+    i <- i+1+  } -    // Verify and remove values.+  // Verify and remove values.+  scoped {+    Int i <- 0+  } in while (i < count) {+    Int new <- ((i + 13) * 3547) % count     scoped {-      Int i <- 0-    } in while (i < count) {-      Int new <- ((i + 13) * 3547) % count-      scoped {-        optional Int value <- tree.get(new)-      } in if (!present(value)) {-        \ LazyStream<Formatted>.new()-            .append("Not found ")-            .append(new)-            .append(" but should have been ")-            .append(i)-            .writeTo(SimpleOutput.error())-      } elif (require(value) != i) {-        \ LazyStream<Formatted>.new()-            .append("Element ")-            .append(new)-            .append(" should have been ")-            .append(i)-            .append(" but was ")-            .append(require(value))-            .writeTo(SimpleOutput.error())-      }-      \ tree.remove(new)-    } update {-      i <- i+1+      optional Int value <- tree.get(new)+    } in if (!present(value)) {+      \ LazyStream<Formatted>.new()+          .append("Not found ")+          .append(new)+          .append(" but should have been ")+          .append(i)+          .writeTo(SimpleOutput.error())+    } elif (require(value) != i) {+      \ LazyStream<Formatted>.new()+          .append("Element ")+          .append(new)+          .append(" should have been ")+          .append(i)+          .append(" but was ")+          .append(require(value))+          .writeTo(SimpleOutput.error())     }+    \ tree.remove(new)+  } update {+    i <- i+1   } }
example/tree/tree.0rp view
@@ -18,7 +18,7 @@   refines KVReader<#k,#v>   #k defines LessThan<#k> -  // Creates a new Tree, e.g., Tree$new().+  // Creates a new Tree, e.g., Tree.new().   @type new () -> (Tree<#k,#v>)    // Normally you do not need to redeclare functions inherited from interfaces.
example/tree/type-tree.0rp view
@@ -4,7 +4,7 @@  * matches the type of the value.  */ concrete TypeTree {-  // Creates a new TypeTree, e.g., TypeTree$new().+  // Creates a new TypeTree, e.g., TypeTree.new().   @type new () -> (TypeTree)    // Sets the value for the given key, inserting if necessary.@@ -45,6 +45,6 @@   defines LessThan<TypeKey<any>>   defines Equals<TypeKey<any>> -  // Creates a new TypeKey, e.g., TypeTree<#x>$new().+  // Creates a new TypeKey, e.g., TypeTree<#x>.new().   @type new () -> (TypeKey<#x>) }
example/tree/type-tree.0rx view
@@ -81,10 +81,10 @@       // The runtime type of value does not matter here; it just needs to be of       // type optional #x at compile time.       //-      // This is more like template meta-programming in C++ than it is like a-      // runtime type cast in Java. The reduce call could in theory be replaced-      // at compile time with either value or empty if parameter substitution-      // happened at compile time. (Like C++ does with templates.)+      // This is more like template meta-programming in C++ than it is like+      // instanceof or reflection in Java. The reduce call could in theory be+      // replaced at compile time with either value or empty if parameter+      // substitution happened at compile time. (Like C++ does with templates.)       return reduce<#x,#y>(value)     } else {       return empty
lib/file/.zeolite-module view
@@ -1,7 +1,7 @@ root: ".." path: "file" public_deps: [-  "../util"+  "lib/util" ] extra_files: [   category_source {
lib/file/tests.0rt view
@@ -17,151 +17,100 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "read and write" {-  success Test.run()+  success } -define Test {-  run () {-    RawFileWriter writer <- RawFileWriter.open("testfile")-    if (present(writer.getFileError())) {-      fail(require(writer.getFileError()))-    }-    RawFileReader reader <- RawFileReader.open("testfile")-    if (present(reader.getFileError())) {-      fail(require(reader.getFileError()))-    }--    String data <- "this is some\x00data"--    Int writeSize <- writer.writeBlock(data)-    if (writeSize != data.readSize()) {-      fail(writeSize)-    }-    if (present(writer.getFileError())) {-      fail(require(writer.getFileError()))-    }--    scoped {-      String data2 <- reader.readBlock(8)-    } in if (data2 != "this is ") {-      fail("\"" + data2 + "\"")-    }-    scoped {-      String data2 <- reader.readBlock(20)-    } in if (data2 != "some\x00data") {-      fail("\"" + data2 + "\"")-    }-    if (present(reader.getFileError())) {-      fail(require(reader.getFileError()))-    }--    if (!reader.pastEnd()) {-      fail("more data in file")-    }+unittest readWrite {+  RawFileWriter writer <- RawFileWriter.open("testfile")+  if (present(writer.getFileError())) {+    fail(require(writer.getFileError()))   }-}--concrete Test {-  @type run () -> ()-}-+  RawFileReader reader <- RawFileReader.open("testfile")+  if (present(reader.getFileError())) {+    fail(require(reader.getFileError()))+  } -testcase "read empty file" {-  success Test.run()-}+  String data <- "this is some\x00data" -define Test {-  run () {-    \ RawFileWriter.open("testfile").freeResource()-    RawFileReader reader <- RawFileReader.open("testfile")+  Int writeSize <- writer.writeBlock(data)+  if (writeSize != data.readSize()) {+    fail(writeSize)+  }+  if (present(writer.getFileError())) {+    fail(require(writer.getFileError()))+  } -    String data <- reader.readBlock(10)-    if (data != "") {-      fail("\"" + data + "\"")-    }-    if (present(reader.getFileError())) {-      fail(require(reader.getFileError()))-    }-    if (!reader.pastEnd()) {-      fail("more data in file")-    }+  scoped {+    String data2 <- reader.readBlock(8)+  } in if (data2 != "this is ") {+    fail("\"" + data2 + "\"")   }-}+  scoped {+    String data2 <- reader.readBlock(20)+  } in if (data2 != "some\x00data") {+    fail("\"" + data2 + "\"")+  }+  if (present(reader.getFileError())) {+    fail(require(reader.getFileError()))+  } -concrete Test {-  @type run () -> ()+  if (!reader.pastEnd()) {+    fail("more data in file")+  } } +unittest readEmpty {+  \ RawFileWriter.open("testfile").freeResource()+  RawFileReader reader <- RawFileReader.open("testfile") -testcase "read missing file" {-  success Test.run()+  String data <- reader.readBlock(10)+  if (data != "") {+    fail("\"" + data + "\"")+  }+  if (present(reader.getFileError())) {+    fail(require(reader.getFileError()))+  }+  if (!reader.pastEnd()) {+    fail("more data in file")+  } } -define Test {-  run () {-    RawFileReader reader <- RawFileReader.open("do-not-create-this-file")-    if (!present(reader.getFileError())) {-      fail("expected file error")-    }+unittest readMissing {+  RawFileReader reader <- RawFileReader.open("do-not-create-this-file")+  if (!present(reader.getFileError())) {+    fail("expected file error")   } } -concrete Test {-  @type run () -> ()+unittest unwritable {+  RawFileWriter writer <- RawFileWriter.open("testfile")+  \ writer.freeResource()+  if (!present(writer.getFileError())) {+    fail("expected file error")+  } }   testcase "read missing file crash" {-  crash Test.run()+  crash   require "do-not-create-this-file"   require "RawFileReader .*originally created" } -define Test {-  run () {-    RawFileReader reader <- RawFileReader.open("do-not-create-this-file")-    \ reader.readBlock(0)-  }-}--concrete Test {-  @type run () -> ()-}---testcase "unwritable file" {-  success Test.run()-}--define Test {-  run () {-    RawFileWriter writer <- RawFileWriter.open("testfile")-    \ writer.freeResource()-    if (!present(writer.getFileError())) {-      fail("expected file error")-    }-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  RawFileReader reader <- RawFileReader.open("do-not-create-this-file")+  \ reader.readBlock(0) }   testcase "unwritable file crash" {-  crash Test.run()+  crash   require "testfile"   require "RawFileWriter .*originally created" } -define Test {-  run () {-    RawFileWriter writer <- RawFileWriter.open("testfile")-    \ writer.freeResource()-    \ writer.writeBlock("")-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  RawFileWriter writer <- RawFileWriter.open("testfile")+  \ writer.freeResource()+  \ writer.writeBlock("") }
lib/math/.zeolite-module view
@@ -1,7 +1,7 @@ root: "../.." path: "lib/math" private_deps: [-  "../../tests"+  "lib/testing" ] extra_files: [   category_source {
lib/math/tests.0rt view
@@ -17,44 +17,113 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "sanity check all functions" {-  success Test.run()+  success } -define Test {-  run () {-    \ Testing.checkBetween<?>(Math.cos(2.0),-0.42,-0.41)-    \ Testing.checkBetween<?>(Math.sin(2.0),0.90,0.91)-    \ Testing.checkBetween<?>(Math.tan(2.0),-2.19,-2.18)-    \ Testing.checkBetween<?>(Math.acos(0.5),1.04,1.05)-    \ Testing.checkBetween<?>(Math.asin(0.5),0.52,0.53)-    \ Testing.checkBetween<?>(Math.atan(0.5),0.46,0.47)-    \ Testing.checkBetween<?>(Math.cosh(2.0),3.76,3.77)-    \ Testing.checkBetween<?>(Math.sinh(2.0),3.62,3.63)-    \ Testing.checkBetween<?>(Math.tanh(2.0),0.96,0.97)-    \ Testing.checkBetween<?>(Math.acosh(2.0),1.31,1.32)-    \ Testing.checkBetween<?>(Math.asinh(2.0),1.44,1.45)-    \ Testing.checkBetween<?>(Math.atanh(0.5),0.54,0.55)-    \ Testing.checkBetween<?>(Math.exp(1.0),2.71,2.72)-    \ Testing.checkBetween<?>(Math.log(9.0),2.19,2.20)-    \ Testing.checkBetween<?>(Math.log10(100.0),1.99,2.01)-    \ Testing.checkBetween<?>(Math.log2(8.0),2.99,3.01)-    \ Testing.checkBetween<?>(Math.pow(2.0,3.0),7.99,8.01)-    \ Testing.checkBetween<?>(Math.sqrt(4.0),1.99,2.01)-    \ Testing.checkBetween<?>(Math.ceil(2.2),2.99,3.01)-    \ Testing.checkBetween<?>(Math.floor(2.2),1.99,2.01)-    \ Testing.checkBetween<?>(Math.fmod(7.0,4.0),2.99,3.01)-    \ Testing.checkBetween<?>(Math.trunc(2.2),1.99,2.01)-    \ Testing.checkBetween<?>(Math.round(2.7),2.99,3.01)-    \ Testing.checkBetween<?>(Math.fabs(-10.0),9.99,10.01)-    if (!Math.isinf(Math.log(0.0))) {-      fail("Failed")-    }-    if (!Math.isnan(Math.sqrt(-1.0))) {-      fail("Failed")-    }+unittest cos {+  \ Testing.checkBetween<?>(Math.cos(2.0),-0.42,-0.41)+}++unittest sin {+  \ Testing.checkBetween<?>(Math.sin(2.0),0.90,0.91)+}++unittest tan {+  \ Testing.checkBetween<?>(Math.tan(2.0),-2.19,-2.18)+}++unittest acos {+  \ Testing.checkBetween<?>(Math.acos(0.5),1.04,1.05)+}++unittest asin {+  \ Testing.checkBetween<?>(Math.asin(0.5),0.52,0.53)+}++unittest atan {+  \ Testing.checkBetween<?>(Math.atan(0.5),0.46,0.47)+}++unittest cosh {+  \ Testing.checkBetween<?>(Math.cosh(2.0),3.76,3.77)+}++unittest sinh {+  \ Testing.checkBetween<?>(Math.sinh(2.0),3.62,3.63)+}++unittest tanh {+  \ Testing.checkBetween<?>(Math.tanh(2.0),0.96,0.97)+}++unittest acosh {+  \ Testing.checkBetween<?>(Math.acosh(2.0),1.31,1.32)+}++unittest asinh {+  \ Testing.checkBetween<?>(Math.asinh(2.0),1.44,1.45)+}++unittest atanh {+  \ Testing.checkBetween<?>(Math.atanh(0.5),0.54,0.55)+}++unittest exp {+  \ Testing.checkBetween<?>(Math.exp(1.0),2.71,2.72)+}++unittest log {+  \ Testing.checkBetween<?>(Math.log(9.0),2.19,2.20)+}++unittest log10 {+  \ Testing.checkBetween<?>(Math.log10(100.0),1.99,2.01)+}++unittest log2 {+  \ Testing.checkBetween<?>(Math.log2(8.0),2.99,3.01)+}++unittest pow {+  \ Testing.checkBetween<?>(Math.pow(2.0,3.0),7.99,8.01)+}++unittest sqrt {+  \ Testing.checkBetween<?>(Math.sqrt(4.0),1.99,2.01)+}++unittest ceil {+  \ Testing.checkBetween<?>(Math.ceil(2.2),2.99,3.01)+}++unittest floor {+  \ Testing.checkBetween<?>(Math.floor(2.2),1.99,2.01)+}++unittest fmod {+  \ Testing.checkBetween<?>(Math.fmod(7.0,4.0),2.99,3.01)+}++unittest trunc {+  \ Testing.checkBetween<?>(Math.trunc(2.2),1.99,2.01)+}++unittest round {+  \ Testing.checkBetween<?>(Math.round(2.7),2.99,3.01)+}++unittest fabs {+  \ Testing.checkBetween<?>(Math.fabs(-10.0),9.99,10.01)+}++unittest isinf {+  if (!Math.isinf(Math.log(0.0))) {+    fail("Failed")   } } -concrete Test {-  @type run () -> ()+unittest isnan {+  if (!Math.isnan(Math.sqrt(-1.0))) {+    fail("Failed")+  } }
+ lib/testing/.zeolite-module view
@@ -0,0 +1,3 @@+root: ".."+path: "testing"+mode: incremental {}
+ lib/testing/helpers.0rp view
@@ -0,0 +1,32 @@+/* -----------------------------------------------------------------------------+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]++$TestsOnly$++concrete Testing {+  @type checkEquals<#x>+    #x requires Formatted+    #x defines Equals<#x>+  (#x /*actual*/, #x /*expected*/) -> ()++  @type checkBetween<#x>+    #x requires Formatted+    #x defines Equals<#x>+    #x defines LessThan<#x>+  (#x /*actual*/, #x /*lower*/, #x /*upper*/) -> ()+}
+ lib/testing/helpers.0rx view
@@ -0,0 +1,60 @@+/* -----------------------------------------------------------------------------+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]++$TestsOnly$++define Testing {+  checkEquals (x,y) {+    if (!#x.equals(x,y)) {+      fail(String.builder()+        .append(x.formatted())+        .append(" is not equal to ")+        .append(y.formatted())+        .build())+    }+  }++  checkBetween (x,l,h) {+    if (!lessEquals<?>(l,h)) {+      fail(String.builder()+        .append("Upper limit ")+        .append(l.formatted())+        .append(" is not at or above lower limit ")+        .append(h.formatted())+        .build())+    }+    if (!lessEquals<?>(l,x) || !lessEquals<?>(x,h)) {+      fail(String.builder()+        .append(x.formatted())+        .append(" is not between ")+        .append(l.formatted())+        .append(" and ")+        .append(h.formatted())+        .build())+    }+  }++  @type lessEquals<#x>+    #x defines Equals<#x>+    #x defines LessThan<#x>+  (#x,#x) -> (Bool)+  lessEquals (x,y) {+    // Using !#x.lessThan(y,x) wouldn't account for NaNs.+    return #x.lessThan(x,y) || #x.equals(x,y)+  }+}
+ lib/testing/tests.0rt view
@@ -0,0 +1,69 @@+/* -----------------------------------------------------------------------------+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 "checkEquals success" {+  success+}++unittest test {+  \ Testing.checkEquals<?>(13,13)+}+++testcase "checkEquals fail" {+  crash+  require stderr "13"+  require stderr "15"+}++unittest test {+  \ Testing.checkEquals<?>(13,15)+}+++testcase "checkBetween success" {+  success+}++unittest test {+  \ Testing.checkBetween<?>(13,13,15)+}+++testcase "checkBetween fail" {+  crash+  require stderr "13"+  require stderr "14"+  require stderr "15"+}++unittest test {+  \ Testing.checkBetween<?>(13,14,15)+}+++testcase "checkBetween bad range" {+  crash+  exclude stderr "14"+  require stderr "13"+  require stderr "15"+}++unittest test {+  \ Testing.checkBetween<?>(14,15,13)+}
lib/util/.zeolite-module view
@@ -7,7 +7,7 @@   } ] private_deps: [-  "../../tests"+  "lib/testing" ] extra_files: [   category_source {
lib/util/Category_Argv.cpp view
@@ -142,7 +142,7 @@   const PrimInt Var_arg1 = (args.At(0))->AsInt();   const PrimInt Var_arg2 = (args.At(1))->AsInt();   if (Var_arg1 < 0 || (Var_arg1 > 0 && Var_arg1 >= GetSize())) {-    FAIL() << "Subsequence position " << Var_arg1 << " is out of bounds";+    FAIL() << "Subsequence index " << Var_arg1 << " is out of bounds";   }   if (Var_arg2 < 0 || Var_arg1 + Var_arg2 > GetSize()) {     FAIL() << "Subsequence size " << Var_arg2 << " is invalid";
lib/util/tests.0rt view
@@ -17,233 +17,135 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "stdout writer" {-  success Test.run()+  success   require stdout "message"   exclude stderr "message" } -define Test {-  run () {-    \ LazyStream<Formatted>.new().append("message").writeTo(SimpleOutput.stdout())-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  \ LazyStream<Formatted>.new().append("message").writeTo(SimpleOutput.stdout()) }   testcase "stderr writer" {-  success Test.run()+  success   require stderr "message"   exclude stdout "message" } -define Test {-  run () {-    \ LazyStream<Formatted>.new().append("message").writeTo(SimpleOutput.stderr())-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  \ LazyStream<Formatted>.new().append("message").writeTo(SimpleOutput.stderr()) }   testcase "error writer" {-  crash Test.run()+  crash   require "message" } -define Test {-  run () {-    \ LazyStream<Formatted>.new().append("message").writeTo(SimpleOutput.error())-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  \ LazyStream<Formatted>.new().append("message").writeTo(SimpleOutput.error()) }  -testcase "iterate String forward" {-  success Test.run()+testcase "iterate ReadIterator" {+  success } -define Test {-  run () {-    String s <- "abcde"-    Int count <- 0-    scoped {-      ReadIterator<Char> iter <- ReadIterator:fromReadPosition<Char>(s)-    } in while (!iter.pastForwardEnd()) {-      if (iter.readCurrent() != s.readPosition(count)) {-        fail(iter.readCurrent())-      }-    } update {-      count <- count+1-      iter <- iter.forward()-    }-    if (count != s.readSize()) {-     fail(count)+unittest forward {+  String s <- "abcde"+  Int count <- 0+  scoped {+    ReadIterator<Char> iter <- ReadIterator:fromReadPosition<Char>(s)+  } in while (!iter.pastForwardEnd()) {+    if (iter.readCurrent() != s.readPosition(count)) {+      fail(iter.readCurrent())     }+  } update {+    count <- count+1+    iter <- iter.forward()   }-}--concrete Test {-  @type run () -> ()-}---testcase "iterate String reverse" {-  success Test.run()+  if (count != s.readSize()) {+    fail(count)+  } } -define Test {-  run () {-    String s <- "abcde"-    Int count <- s.readSize()-1-    scoped {-      ReadIterator<Char> iter <- ReadIterator:fromReadPositionAt<Char>(s,count)-    } in while (!iter.pastReverseEnd()) {-      if (iter.readCurrent() != s.readPosition(count)) {-        fail(iter.readCurrent())-      }-    } update {-      count <- count-1-      iter <- iter.reverse()-    }-    if (count != -1) {-     fail(count)+unittest reverse {+  String s <- "abcde"+  Int count <- s.readSize()-1+  scoped {+    ReadIterator<Char> iter <- ReadIterator:fromReadPositionAt<Char>(s,count)+  } in while (!iter.pastReverseEnd()) {+    if (iter.readCurrent() != s.readPosition(count)) {+      fail(iter.readCurrent())     }+  } update {+    count <- count-1+    iter <- iter.reverse()   }-}--concrete Test {-  @type run () -> ()+  if (count != -1) {+    fail(count)+  } }  -testcase "Argv is set and available" {-  success Test.run()-  require stdout "/testcase$"+testcase "Argv checks" {+  success+  args "arg1" "arg2" "arg3" "arg4" } -define Test {-  run () {-    Int count <- Argv.global().readSize()-    if (count != 1) {-      fail(count)-    }-    String name <- Argv.global().readPosition(0)-    \ LazyStream<Formatted>.new()-        .append(name)-        .append("\n")-        .writeTo(SimpleOutput.stdout())+unittest global {+  Int count <- Argv.global().readSize()+  if (count != 5) {+    fail(count)   }+  \ Testing.checkEquals<?>(Argv.global().readPosition(0),"testcase")+  \ Testing.checkEquals<?>(Argv.global().readPosition(1),"arg1")+  \ Testing.checkEquals<?>(Argv.global().readPosition(2),"arg2")+  \ Testing.checkEquals<?>(Argv.global().readPosition(3),"arg3")+  \ Testing.checkEquals<?>(Argv.global().readPosition(4),"arg4") } -concrete Test {-  @type run () -> ()+unittest subSequence {+  ReadPosition<String> argv <- Argv.global().subSequence(2,2)+  Int count <- argv.readSize()+  if (count != 2) {+    fail(count)+  }+  \ Testing.checkEquals<?>(argv.readPosition(0),"arg2")+  \ Testing.checkEquals<?>(argv.readPosition(1),"arg3") }  -testcase "Argv subSequence" {-  success Test.run()-  require stdout "/testcase$"-}--define Test {-  run () {-    ReadPosition<String> argv <- Argv.global().subSequence(0,1)-    Int count <- argv.readSize()-    if (count != 1) {-      fail(count)-    }-    String name <- argv.readPosition(0)-    \ LazyStream<Formatted>.new()-        .append(name)-        .append("\n")-        .writeTo(SimpleOutput.stdout())-  }+testcase "Argv readPosition out of bounds" {+  crash+  require "index 5" } -concrete Test {-  @type run () -> ()+unittest test {+  \ Argv.global().readPosition(5) }   testcase "Argv subSequence out of bounds" {-  crash Test.run()-  require "position 5"-}--define Test {-  run () {-    ReadPosition<String> argv <- Argv.global().subSequence(5,1)-  }+  crash+  require "index 5" } -concrete Test {-  @type run () -> ()+unittest test {+  \ Argv.global().subSequence(5,1) }  -testcase "TextReader splits lines correctly" {-  success Test.run()-}--concrete FakeFile {-  refines BlockReader<String>--  @type create () -> (FakeFile)+testcase "TextReader checks" {+  success } -define FakeFile {-  @value Int counter--  create () {-    return FakeFile{ 0 }-  }--  readBlock (_) {-    cleanup {-      counter <- counter+1-    } in if (counter == 0) {-      return "this is a "-    } elif (counter == 1) {-      return "partial line\nwith "-    } elif (counter == 2) {-      return "some more data\nand\nmore lines"-    } elif (counter == 3) {-      return "\nunfinished"-    } else {-      fail("too many reads")-    }-  }--  pastEnd () {-    return counter > 3-  }+concrete Helper {+  @type checkNext (TextReader,String) -> () } -define Test {-  run () {-    TextReader reader <- TextReader.fromBlockReader(FakeFile.create())-    \ checkNext(reader,"this is a partial line")-    \ checkNext(reader,"with some more data")-    \ checkNext(reader,"and")-    \ checkNext(reader,"more lines")-    \ checkNext(reader,"unfinished")-    if (!reader.pastEnd()) {-      fail("not past end")-    }-    if (reader.readNextLine() != "") {-      fail("reused data")-    }-  }--  @type checkNext (TextReader,String) -> ()+define Helper {   checkNext (reader,line) {     if (reader.pastEnd()) {       fail("past end")@@ -255,15 +157,6 @@   } } -concrete Test {-  @type run () -> ()-}---testcase "TextReader readAll" {-  success Test.run()-}- concrete FakeFile {   refines BlockReader<String> @@ -298,103 +191,72 @@   } } -define Test {-  run () {-    String allContents <- TextReader.readAll(FakeFile.create())-    \ Testing.check<?>(allContents,"this is a partial line\nwith some more data\nand\nmore lines\nunfinished")-  }+unittest correctSplit {+    TextReader reader <- TextReader.fromBlockReader(FakeFile.create())+    \ Helper.checkNext(reader,"this is a partial line")+    \ Helper.checkNext(reader,"with some more data")+    \ Helper.checkNext(reader,"and")+    \ Helper.checkNext(reader,"more lines")+    \ Helper.checkNext(reader,"unfinished")+    if (!reader.pastEnd()) {+      fail("not past end")+    }+    if (reader.readNextLine() != "") {+      fail("reused data")+    } } -concrete Test {-  @type run () -> ()+unittest readAll {+  String allContents <- TextReader.readAll(FakeFile.create())+  \ Testing.checkEquals<?>(allContents,"this is a partial line\nwith some more data\nand\nmore lines\nunfinished") }  -testcase "ErrorOr value" {-  success Test.run()+testcase "ErrorOr checks" {+  success } -define Test {-  run () {-    ErrorOr<Int> value <- ErrorOr:value<Int>(10)-    if (value.isError()) {-      fail("Failed")-    }-    \ Testing.check<?>(value.getValue(),10)+unittest withValue {+  ErrorOr<Int> value <- ErrorOr:value<Int>(10)+  if (value.isError()) {+    fail("Failed")   }-}--concrete Test {-  @type run () -> ()-}---testcase "ErrorOr getError() crashes with value" {-  crash Test.run()-  require "empty"+  \ Testing.checkEquals<?>(value.getValue(),10) } -define Test {-  run () {-    ErrorOr<Int> value <- ErrorOr:value<Int>(10)-    \ value.getError()+unittest withError {+  ErrorOr<String> value <- ErrorOr:error("error message")+  if (!value.isError()) {+    fail("Failed")   }+  \ Testing.checkEquals<?>(value.getError().formatted(),"error message") } -concrete Test {-  @type run () -> ()+unittest convertError {+  scoped {+    ErrorOr<String> error <- ErrorOr:error("error message")+  } in ErrorOr<Int> value <- error.convertError()+  \ Testing.checkEquals<?>(value.getError().formatted(),"error message") }  -testcase "ErrorOr error" {-  success Test.run()-}--define Test {-  run () {-    ErrorOr<String> value <- ErrorOr:error("error message")-    if (!value.isError()) {-      fail("Failed")-    }-    \ Testing.check<?>(value.getError().formatted(),"error message")-  }+testcase "ErrorOr getError() crashes with value" {+  crash+  require "empty" } -concrete Test {-  @type run () -> ()+unittest test {+  ErrorOr<Int> value <- ErrorOr:value<Int>(10)+  \ value.getError() }   testcase "ErrorOr getValue() crashes with error" {-  crash Test.run()+  crash   require "error message" } -define Test {-  run () {-    ErrorOr<String> value <- ErrorOr:error("error message")-    \ value.getValue()-  }-}--concrete Test {-  @type run () -> ()-}---testcase "ErrorOr convert error" {-  success Test.run()-}--define Test {-  run () {-    scoped {-      ErrorOr<String> error <- ErrorOr:error("error message")-    } in ErrorOr<Int> value <- error.convertError()-    \ Testing.check<?>(value.getError().formatted(),"error message")-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  ErrorOr<String> value <- ErrorOr:error("error message")+  \ value.getValue() }
src/Base/CompileError.hs view
@@ -68,15 +68,19 @@  (<??) :: CompileErrorM m => m a -> String -> m a (<??) = withContextM+infixl 1 <??  (??>) :: CompileErrorM m => String -> m a -> m a (??>) = flip withContextM+infixr 1 ??>  (<!!) :: CompileErrorM m => m a -> String -> m a (<!!) = summarizeErrorsM+infixl 1 <!!  (!!>) :: CompileErrorM m => String -> m a -> m a (!!>) = flip summarizeErrorsM+infixr 1 !!>  collectAllM_ :: (Foldable f, CompileErrorM m) => f (m a) -> m () collectAllM_ = fmap (const ()) . collectAllM
src/Base/CompileInfo.hs view
@@ -60,9 +60,9 @@ import Base.CompileError  -type CompileInfo a = CompileInfoT Identity a+type CompileInfo = CompileInfoT Identity -type CompileInfoIO a = CompileInfoT IO a+type CompileInfoIO = CompileInfoT IO  data CompileInfoT m a =   CompileInfoT {
src/Base/Mergeable.hs view
@@ -23,6 +23,8 @@ module Base.Mergeable (   Mergeable(..),   PreserveMerge(..),+  (<||>),+  (<&&>), ) where  import Data.Map as Map hiding (foldr)@@ -36,10 +38,18 @@   type T a :: *   convertMerge :: Mergeable b => (T a -> b) -> a -> b +(<||>) :: Mergeable a => a -> a -> a+(<||>) x y = mergeAny [x,y]+infixl 2 <||>++(<&&>) :: Mergeable a => a -> a -> a+(<&&>) x y = mergeAll [x,y]+infixl 2 <&&>+ instance Mergeable Bool where   mergeAny = foldr (||) False   mergeAll = foldr (&&) True  instance (Ord k, Mergeable a) => Mergeable (Map k a) where-  mergeAny = Map.fromListWith (\x y -> mergeAny [x,y]) . foldr ((++) . Map.toList) []-  mergeAll = Map.fromListWith (\x y -> mergeAll [x,y]) . foldr ((++) . Map.toList) []+  mergeAny = Map.fromListWith (<||>) . foldr ((++) . Map.toList) []+  mergeAll = Map.fromListWith (<&&>) . foldr ((++) . Map.toList) []
src/Cli/Compiler.hs view
@@ -210,8 +210,8 @@             coNamespace = case c `Map.lookup` ca of                                Just ns2 -> ns2                                Nothing  -> NoNamespace,-            coUsesNamespace = [ns0,ns1],-            coUsesCategory = ds2,+            coUsesNamespace = Set.fromList [ns0,ns1],+            coUsesCategory = Set.fromList ds2,             coOutput = []           }     compileExtraSource _ _ paths (OtherSource f2) = do@@ -314,9 +314,9 @@   [WithVisibility (AnyCategory c)] -> LanguageModule c createLanguageModule ex ss em cs = lm where   lm = LanguageModule {-      lmPublicNamespaces  = map wvData $ apply ns [with    FromDependency,without ModuleOnly,without TestsOnly],-      lmPrivateNamespaces = map wvData $ apply ns [with    FromDependency,with    ModuleOnly,without TestsOnly],-      lmLocalNamespaces   = map wvData $ apply ns [without FromDependency],+      lmPublicNamespaces  = Set.fromList $ map wvData $ apply ns [with    FromDependency,without ModuleOnly],+      lmPrivateNamespaces = Set.fromList $ map wvData $ apply ns [with    FromDependency,with    ModuleOnly],+      lmLocalNamespaces   = Set.fromList $ map wvData $ apply ns [without FromDependency],       lmPublicDeps        = map wvData $ apply cs [with    FromDependency,without ModuleOnly,without TestsOnly],       lmPrivateDeps       = map wvData $ apply cs [with    FromDependency,with    ModuleOnly,without TestsOnly],       lmTestingDeps       = map wvData $ apply cs [with    FromDependency,with TestsOnly],
src/Cli/Programs.hs view
@@ -61,7 +61,8 @@ data TestCommand =   TestCommand {     tcBinary :: String,-    tcPath :: String+    tcPath :: String,+    tcArgs :: [String]   }   deriving (Show) 
src/Cli/RunCompiler.hs view
@@ -70,7 +70,7 @@     processResults passed failed rs       | isCompileError rs =         (fromCompileInfo rs) <!!-          ("\nPassed: " ++ show passed ++ " test(s), Failed: " ++ show failed ++ " test(s)")+          "\nPassed: " ++ show passed ++ " test(s), Failed: " ++ show failed ++ " test(s)"       | otherwise =         errorFromIO $ hPutStrLn stderr $ "\nPassed: " ++ show passed ++ " test(s), Failed: " ++ show failed ++ " test(s)" @@ -103,24 +103,24 @@     msMode = (CompileBinary c fn (absolute </> show c) []),     msForce = f   }-  compileModule resolver backend spec <?? ("In compilation of \"" ++ f2' ++ "\"")+  compileModule resolver backend spec <?? "In compilation of \"" ++ f2' ++ "\""   errorFromIO $ removeDirectoryRecursive dir  runCompiler resolver backend (CompileOptions h _ _ ds _ _ p CompileRecompileRecursive f) = do-  foldM (recursive resolver) Set.empty ds >> return () where-    recursive r da d0 = do-      isSystem <- isSystemModule r p d0+  foldM (recursive resolver) Set.empty (map ((,) p) ds) >> return () where+    recursive r da (p2,d0) = do+      isSystem <- isSystemModule r p2 d0       if isSystem          then do-           compileWarningM $ "Skipping system module " ++ d0 ++ "."+           compileWarningM $ "Skipping system dependency " ++ d0 ++ " for " ++ p2 ++ "."            return da          else do-           d <- errorFromIO $ canonicalizePath (p </> d0)+           d <- errorFromIO $ canonicalizePath (p2 </> d0)            rm <- loadRecompile d            if mcPath rm `Set.member` da                then return da                else do-                 let ds3 = map (\d2 -> d </> d2) (mcPublicDeps rm ++ mcPrivateDeps rm)+                 let ds3 = map ((,) d) (mcPublicDeps rm ++ mcPrivateDeps rm)                  da' <- foldM (recursive r) (mcPath rm `Set.insert` da) ds3                  runCompiler resolver backend (CompileOptions h [] [] [d] [] [] p CompileRecompile f)                  return da'@@ -155,7 +155,7 @@              msMode = m,              msForce = f            }-           compileModule resolver backend spec <?? ("In compilation of module \"" ++ d ++ "\"")+           compileModule resolver backend spec <?? "In compilation of module \"" ++ d ++ "\""  runCompiler resolver backend (CompileOptions _ is is2 ds _ _ p CreateTemplates f) = mapM_ compileSingle ds where   compilerHash = getCompilerHash backend@@ -167,7 +167,7 @@     deps1 <- loadPublicDeps compilerHash f Map.empty (base:as)     deps2 <- loadPublicDeps compilerHash f (mapMetadata deps1) as2     path <- errorFromIO $ canonicalizePath p-    createModuleTemplates resolver path d deps1 deps2 <?? ("In module \"" ++ d' ++ "\"")+    createModuleTemplates resolver path d deps1 deps2 <?? "In module \"" ++ d' ++ "\""  runCompiler resolver backend (CompileOptions h is is2 ds es ep p m f) = mapM_ compileSingle ds where   compileSingle d = do
src/Cli/TestRunner.hs view
@@ -22,13 +22,15 @@  import Control.Arrow (second) import Control.Monad (when)-import Data.List (isSuffixOf,nub)+import Control.Monad.IO.Class+import Data.List (isSuffixOf,nub,sort) import System.Directory import System.IO import System.Posix.Temp (mkdtemp) import System.FilePath import Text.Parsec import Text.Regex.TDFA -- Not safe!+import qualified Data.Map as Map  import Base.CompileError import Base.CompileInfo@@ -40,6 +42,7 @@ import Module.ProcessMetadata import Parser.SourceFile import Types.IntegrationTest+import Types.Procedure import Types.TypeCategory  @@ -56,33 +59,57 @@         return ((0,1),ts >> return ())       | otherwise = do           let (_,ts') = getCompileSuccess ts-          allResults <- sequence $ map runSingle ts'-          let passed = length $ filter (not . isCompileError) allResults-          let failed = length $ filter isCompileError allResults-          return ((passed,failed),collectAllM_ allResults)+          allResults <- mapErrorsM runSingle ts'+          let passed = sum $ map (fst . fst) allResults+          let failed = sum $ map (snd . fst) allResults+          let result = collectAllM_ $ map snd allResults+          return ((passed,failed),result)+     runSingle t = do       let name = "\"" ++ ithTestName (itHeader t) ++ "\" (from " ++ f ++ ")"       let context = formatFullContextBrace (ithContext $ itHeader t)-      errorFromIO $ hPutStrLn stderr $ "\n*** Executing test " ++ name ++ " ***"-      outcome <- fmap (("\nIn test \"" ++ ithTestName (itHeader t) ++ "\"" ++ context) ??>) $-                   run (ithResult $ itHeader t) (itCategory t) (itDefinition t)-      if isCompileError outcome-         then errorFromIO $ hPutStrLn stderr $ "*** Test " ++ name ++ " failed ***"-         else errorFromIO $ hPutStrLn stderr $ "*** Test " ++ name ++ " passed ***"-      return outcome+      let scope = "\nIn testcase \"" ++ ithTestName (itHeader t) ++ "\"" ++ context+      errorFromIO $ hPutStrLn stderr $ "\n*** Executing testcase " ++ name ++ " ***"+      result <- toCompileInfo $ run (ithResult $ itHeader t) (ithArgs $ itHeader t) (itCategory t) (itDefinition t) (itTests t)+      if isCompileError result+         then return ((0,1),scope ??> (result >> return ()))+         else do+           let allResults = getCompileSuccess result+           let passed = length $ filter (not . isCompileError) allResults+           let failed = length $ filter isCompileError allResults+           let combined = scope ??> collectAllM_ allResults+           if failed > 0+             then errorFromIO $ hPutStrLn stderr $ "*** Some tests in testcase " ++ name ++ " failed ***"+             else errorFromIO $ hPutStrLn stderr $ "*** All tests in testcase " ++ name ++ " passed ***"+           return ((passed,failed),combined) -    run (ExpectCompileError _ rs es) cs ds = do-      let result = compileAll Nothing cs ds+    run (ExpectCompileError _ rs es) args cs ds ts = do+      let result = compileAll args cs ds ts       if not $ isCompileError result-         then undefined  -- Should be caught in compileAll.-         else return $ do+         then compileErrorM "Expected compilation failure"+         else fmap (:[]) $ return $ do            let warnings = show $ getCompileWarnings result            let errors   = show $ getCompileError result            checkContent rs es (lines warnings ++ lines errors) [] [] -    run (ExpectRuntimeError   _ e rs es) cs ds = execute False e rs es cs ds-    run (ExpectRuntimeSuccess _ e rs es) cs ds = execute True  e rs es cs ds+    run (ExpectCompiles _ rs es) args cs ds ts = do+      let result = compileAll args cs ds ts+      if isCompileError result+         then fromCompileInfo result >> return []+         else fmap (:[]) $ return $ do+           let warnings = show $ getCompileWarnings result+           checkContent rs es (lines warnings) [] [] +    run (ExpectRuntimeError _ rs es) args cs ds ts = do+      when (length ts /= 1) $ compileErrorM "Exactly one unittest is required when crash is expected"+      uniqueTestNames ts+      execute False rs es args cs ds ts++    run (ExpectRuntimeSuccess _ rs es) args cs ds ts = do+      when (null ts) $ compileErrorM "At least one unittest is required when success is expected"+      uniqueTestNames ts+      execute True rs es args cs ds ts+     checkContent rs es comp err out = do       let cr = checkRequired rs comp err out       let ce = checkExcluded es comp err out@@ -99,42 +126,44 @@          then collectAllM_ [cr,ce,compError,errError,outError]          else collectAllM_ [cr,ce] -    execute s2 e rs es cs ds = toCompileInfo $ do-      let result = compileAll (Just e) cs ds+    uniqueTestNames ts = do+      let ts' = Map.fromListWith (++) $ map (\t -> (tpName t,[t])) ts+      mapErrorsM_ testClash $ Map.toList ts'+    testClash (_,[_]) = return ()+    testClash (n,ts) = "unittest " ++ show n ++ " is defined multiple times" !!>+      (mapErrorsM_ (compileErrorM . ("Defined at " ++) . formatFullContext) $ sort $ map tpContext ts)++    execute s2 rs es args cs ds ts = do+      let result = compileAll args cs ds ts       if isCompileError result-         then fromCompileInfo result >> return ()+         then return [result >> return ()]          else do-           let warnings = getCompileWarnings result-           let (xx,main) = getCompileSuccess result+           let (xx,main,fs) = getCompileSuccess result            (dir,binaryName) <- createBinary main xx-           let command = TestCommand binaryName (takeDirectory binaryName)-           (TestCommandResult s2' out err) <- runTestCommand b command-           case (s2,s2') of-                (True,False) -> collectAllM_ $ (asCompileError result):(map compileErrorM $ err ++ out)-                (False,True) ->-                  if isEmptyCompileMessage warnings-                     then compileErrorM "Expected runtime failure"-                     else collectAllM_ [compileErrorM "Expected runtime failure",-                                        asCompileError result <?? "\nOutput from compiler:"]-                _ -> do-                  let result2 = checkContent rs es (lines $ show warnings) err out-                  when (not $ isCompileError result2) $ errorFromIO $ removeDirectoryRecursive dir-                  fromCompileInfo result2+           results <- liftIO $ sequence $ map (toCompileInfo . executeTest binaryName rs es result s2) fs+           when (not $ any isCompileError results) $ errorFromIO $ removeDirectoryRecursive dir+           return results -    compileAll e cs ds = do+    executeTest binary rs es res s2 (f2,c) = printOutcome $ "\nIn unittest " ++ show f2 ++ formatFullContextBrace c ??> do+      let command = TestCommand binary (takeDirectory binary) [show f2]+      (TestCommandResult s2' out err) <- runTestCommand b command+      case (s2,s2') of+           (True,False) -> collectAllM_ $ (asCompileError res):(map compileErrorM $ err ++ out)+           (False,True) -> collectAllM_ [compileErrorM "Expected runtime failure",+                                         asCompileError res <?? "\nOutput from compiler:"]+           _ -> fromCompileInfo $ checkContent rs es (lines $ show $ getCompileWarnings res) err out+      where+        printOutcome outcome = do+          failed <- isCompileErrorM outcome+          if failed+             then errorFromIO $ hPutStrLn stderr $ "--- unittest " ++ show f2 ++ " failed ---"+             else errorFromIO $ hPutStrLn stderr $ "--- unittest " ++ show f2 ++ " passed ---"+          outcome++    compileAll args cs ds ts = do       let ns1 = StaticNamespace $ privateNamespace s       let cs' = map (setCategoryNamespace ns1) cs-      let xs = PrivateSource {-          psNamespace = ns1,-          psTesting = True,-          psCategory = cs',-          psDefine = ds-        }-      xx <- compileLanguageModule cm [xs]-      main <- case e of-                   Just e2 -> compileTestMain cm xs e2-                   Nothing -> compileErrorM ""-      return (xx,main)+      compileTestsModule cm ns1 args cs' ds ts      checkRequired rs comp err out = mapErrorsM_ (checkSubsetForRegex True  comp err out) rs     checkExcluded es comp err out = mapErrorsM_ (checkSubsetForRegex False comp err out) es
src/Compilation/CompilerState.hs view
@@ -58,6 +58,8 @@   csPrimNamedReturns,   csPushCleanup,   csRegisterReturn,+  csReleaseExprMacro,+  csReserveExprMacro,   csRequiresTypes,   csResolver,   csSameType,@@ -87,6 +89,7 @@ import Base.CompileError import Types.DefinedCategory import Types.Positional+import Types.Pragma (MacroName) import Types.Procedure import Types.TypeCategory import Types.TypeInstance@@ -123,7 +126,9 @@   ccStartCleanup :: a -> m a   ccPushCleanup :: a -> CleanupSetup a s -> m a   ccGetCleanup :: a -> JumpType -> m (CleanupSetup a s)-  ccExprLookup :: a -> [c] -> String -> m (Expression c)+  ccExprLookup :: a -> [c] -> MacroName -> m (Expression c)+  ccReserveExprMacro :: a -> [c] -> MacroName -> m a+  ccReleaseExprMacro :: a -> [c] -> MacroName -> m a   ccSetNoTrace :: a -> Bool -> m a   ccGetNoTrace :: a -> m Bool @@ -176,15 +181,19 @@  (<???) :: CompileErrorM m => CompilerState a m b -> String -> CompilerState a m b (<???) x s = mapStateT (<?? s) x+infixl 1 <???  (???>) :: CompileErrorM m => String -> CompilerState a m b -> CompilerState a m b (???>) s x = mapStateT (s ??>) x+infixr 1 ???>  (<!!!) :: CompileErrorM m => CompilerState a m b -> String -> CompilerState a m b (<!!!) x s = mapStateT (<!! s) x+infixl 1 <!!!  (!!!>) :: CompileErrorM m => String -> CompilerState a m b -> CompilerState a m b (!!!>) s x = mapStateT (s !!>) x+infixr 1 !!!>  resetBackgroundStateT :: CompileErrorM m => CompilerState a m b -> CompilerState a m b resetBackgroundStateT x = mapStateT resetBackgroundM x@@ -280,8 +289,14 @@ csGetCleanup :: CompilerContext c m s a => JumpType -> CompilerState a m (CleanupSetup a s) csGetCleanup j = fmap (\x -> ccGetCleanup x j) get >>= lift -csExprLookup :: CompilerContext c m s a => [c] -> String -> CompilerState a m (Expression c)+csExprLookup :: CompilerContext c m s a => [c] -> MacroName -> CompilerState a m (Expression c) csExprLookup c n = fmap (\x -> ccExprLookup x c n) get >>= lift++csReserveExprMacro :: CompilerContext c m s a => [c] -> MacroName -> CompilerState a m ()+csReserveExprMacro c n = fmap (\x -> ccReserveExprMacro x c n) get >>= lift >>= put++csReleaseExprMacro :: CompilerContext c m s a => [c] -> MacroName -> CompilerState a m ()+csReleaseExprMacro c n = fmap (\x -> ccReleaseExprMacro x c n) get >>= lift >>= put  csSetNoTrace :: CompilerContext c m s a => Bool -> CompilerState a m () csSetNoTrace t = fmap (\x -> ccSetNoTrace x t) get >>= lift >>= put
src/Compilation/ProcedureContext.hs view
@@ -38,6 +38,7 @@ import Types.DefinedCategory import Types.GeneralType import Types.Positional+import Types.Pragma (MacroName) import Types.Procedure import Types.TypeCategory import Types.TypeInstance@@ -68,10 +69,11 @@     pcCleanupSetup :: [CleanupSetup (ProcedureContext c) [String]],     pcInCleanup :: Bool,     pcExprMap :: ExprMap c,+    pcReservedMacros :: [(MacroName,[c])],     pcNoTrace :: Bool   } -type ExprMap c = Map.Map String (Expression c)+type ExprMap c = Map.Map MacroName (Expression c)  data ReturnValidation c =   ValidatePositions {@@ -119,6 +121,7 @@       pcCleanupSetup = pcCleanupSetup ctx,       pcInCleanup = pcInCleanup ctx,       pcExprMap = pcExprMap ctx,+      pcReservedMacros = pcReservedMacros ctx,       pcNoTrace = pcNoTrace ctx     }   ccGetRequired = return . pcRequiredTypes@@ -152,7 +155,7 @@       compileErrorM $ "Use explicit type conversion to call " ++ show n ++ " from " ++ show t     getFromAll ts = do       collectFirstM ts <!!-        ("Function " ++ show n ++ " not available for type " ++ show t ++ formatFullContextBrace c)+        "Function " ++ show n ++ " not available for type " ++ show t ++ formatFullContextBrace c     getFromSingle (JustParamName _ p) = do       fa <- ccAllFilters ctx       fs <- case p `Map.lookup` fa of@@ -161,7 +164,7 @@       let ts = map tfType $ filter isRequiresFilter fs       let ds = map dfType $ filter isDefinesFilter  fs       collectFirstM (map (getFunction . Just) ts ++ map checkDefine ds) <!!-        ("Function " ++ show n ++ " not available for param " ++ show p ++ formatFullContextBrace c)+        "Function " ++ show n ++ " not available for param " ++ show p ++ formatFullContextBrace c     getFromSingle (JustTypeInstance t2)       -- Same category as the procedure itself.       | tiName t2 == pcType ctx =@@ -186,7 +189,7 @@         compileErrorM $ "Function " ++ show n ++ " in " ++ show t2 ++                        " is a category function" ++ formatFullContextBrace c       paired <- processPairs alwaysPair ps1 ps2 <??-        ("In external function call at " ++ formatFullContext c)+        "In external function call at " ++ formatFullContext c       let assigned = Map.fromList paired       uncheckedSubFunction assigned f     subAndCheckFunction t2 _ _ _ =@@ -197,7 +200,7 @@     | t /= pcType ctx =       compileErrorM $ "Category " ++ show (pcType ctx) ++ " cannot initialize values from " ++                      show t ++ formatFullContextBrace c-    | otherwise = ("In initialization at " ++ formatFullContext c) ??> do+    | otherwise = "In initialization at " ++ formatFullContext c ??> do       let t' = TypeInstance (pcType ctx) as       r <- ccResolver ctx       allFilters <- ccAllFilters ctx@@ -224,7 +227,7 @@           mapErrorsM (uncheckedSubFilter $ getValueForParam fm) fs         checkInit r fa (MemberValue c2 n t0) (i,t1) = do           checkValueAssignment r fa t1 t0 <??-            ("In initializer " ++ show i ++ " for " ++ show n ++ formatFullContextBrace c2)+            "In initializer " ++ show i ++ " for " ++ show n ++ formatFullContextBrace c2         subSingle pa (DefinedMember c2 _ t2 n _) = do           t2' <- uncheckedSubValueType (getValueForParam pa) t2           return $ MemberValue c2 n t2'@@ -263,6 +266,7 @@         pcCleanupSetup = pcCleanupSetup ctx,         pcInCleanup = pcInCleanup ctx,         pcExprMap = pcExprMap ctx,+        pcReservedMacros = pcReservedMacros ctx,         pcNoTrace = pcNoTrace ctx       }   ccCheckVariableInit ctx c n =@@ -295,6 +299,7 @@       pcCleanupSetup = pcCleanupSetup ctx,       pcInCleanup = pcInCleanup ctx,       pcExprMap = pcExprMap ctx,+      pcReservedMacros = pcReservedMacros ctx,       pcNoTrace = pcNoTrace ctx     }   ccGetOutput = return . pcOutput@@ -322,6 +327,7 @@         pcCleanupSetup = pcCleanupSetup ctx,         pcInCleanup = pcInCleanup ctx,         pcExprMap = pcExprMap ctx,+        pcReservedMacros = pcReservedMacros ctx,         pcNoTrace = pcNoTrace ctx       }   ccUpdateAssigned ctx n = update (pcReturns ctx) where@@ -349,6 +355,7 @@         pcCleanupSetup = pcCleanupSetup ctx,         pcInCleanup = pcInCleanup ctx,         pcExprMap = pcExprMap ctx,+        pcReservedMacros = pcReservedMacros ctx,         pcNoTrace = pcNoTrace ctx       }     update _ = return ctx@@ -376,6 +383,7 @@       pcCleanupSetup = pcCleanupSetup ctx,       pcInCleanup = pcInCleanup ctx,       pcExprMap = pcExprMap ctx,+      pcReservedMacros = pcReservedMacros ctx,       pcNoTrace = pcNoTrace ctx     }     where@@ -417,6 +425,7 @@         pcCleanupSetup = pcCleanupSetup ctx,         pcInCleanup = pcInCleanup ctx,         pcExprMap = pcExprMap ctx,+        pcReservedMacros = pcReservedMacros ctx,         pcNoTrace = pcNoTrace ctx       }     where@@ -426,17 +435,17 @@                        Just vs2 -> vs2         -- Check for a count match first, to avoid the default error message.         processPairs_ alwaysPair (fmap pvType rs) vs' <??-          ("In procedure return at " ++ formatFullContext c)+          "In procedure return at " ++ formatFullContext c         processPairs_ checkReturnType rs (Positional $ zip ([0..] :: [Int]) $ pValues vs') <??-          ("In procedure return at " ++ formatFullContext c)+          "In procedure return at " ++ formatFullContext c         return (ValidatePositions rs)         where           checkReturnType ta0@(PassedValue _ t0) (n,t) = do             r <- ccResolver ctx             pa <- ccAllFilters ctx             checkValueAssignment r pa t t0 <!!-              ("Cannot convert " ++ show t ++ " to " ++ show ta0 ++ " in return " ++-               show n ++ " at " ++ formatFullContext c)+              "Cannot convert " ++ show t ++ " to " ++ show ta0 ++ " in return " +++               show n ++ " at " ++ formatFullContext c       check (ValidateNames ns ts ra) = do         case vs of              Just _  -> check (ValidatePositions ts) >> return ()@@ -475,6 +484,7 @@         pcCleanupSetup = pcCleanupSetup ctx,         pcInCleanup = pcInCleanup ctx,         pcExprMap = pcExprMap ctx,+        pcReservedMacros = pcReservedMacros ctx,         pcNoTrace = pcNoTrace ctx       }   ccStartLoop ctx l =@@ -502,6 +512,7 @@         pcCleanupSetup = LoopBoundary:(pcCleanupSetup ctx),         pcInCleanup = pcInCleanup ctx,         pcExprMap = pcExprMap ctx,+        pcReservedMacros = pcReservedMacros ctx,         pcNoTrace = pcNoTrace ctx       }   ccGetLoop = return . pcLoopSetup@@ -531,6 +542,7 @@         pcCleanupSetup = pcCleanupSetup ctx,         pcInCleanup = True,         pcExprMap = pcExprMap ctx,+        pcReservedMacros = pcReservedMacros ctx,         pcNoTrace = pcNoTrace ctx       }     where@@ -565,6 +577,7 @@         pcCleanupSetup = cs:(pcCleanupSetup ctx),         pcInCleanup = pcInCleanup ctx,         pcExprMap = pcExprMap ctx,+        pcReservedMacros = pcReservedMacros ctx,         pcNoTrace = pcNoTrace ctx       }   ccGetCleanup ctx j = return combined where@@ -575,8 +588,73 @@     combine cs = CleanupSetup (concat $ map csReturnContext cs) (concat $ map csCleanup cs)   ccExprLookup ctx c n =     case n `Map.lookup` pcExprMap ctx of-         Nothing -> compileErrorM $ "Env expression " ++ n ++ " is not defined" ++ formatFullContextBrace c-         Just e -> return e+         Nothing -> compileErrorM $ "Env expression " ++ show n ++ " is not defined" ++ formatFullContextBrace c+         Just e -> do+           checkReserved (pcReservedMacros ctx) [(n,c)]+           return e+    where+      checkReserved [] _ = return ()+      checkReserved (m@(n2,_):ms) rs+        | n2 /= n = checkReserved ms (m:rs)+        | otherwise = (mapErrorsM_ singleError (m:rs)) <!!+            "Expression macro " ++ show n ++ " references itself"+      singleError (n2,c2) = compileErrorM $ show n2 ++ " expanded at " ++ formatFullContext c2+  ccReserveExprMacro ctx c n =+    return $ ProcedureContext {+        pcScope = pcScope ctx,+        pcType = pcType ctx,+        pcExtParams = pcExtParams ctx,+        pcIntParams = pcIntParams ctx,+        pcMembers = pcMembers ctx,+        pcCategories = pcCategories ctx,+        pcAllFilters = pcAllFilters ctx,+        pcExtFilters = pcExtFilters ctx,+        pcIntFilters = pcIntFilters ctx,+        pcParamScopes = pcParamScopes ctx,+        pcFunctions = pcFunctions ctx,+        pcVariables = pcVariables ctx,+        pcReturns = pcReturns ctx,+        pcJumpType = pcJumpType ctx,+        pcIsNamed = pcIsNamed ctx,+        pcPrimNamed = pcPrimNamed ctx,+        pcRequiredTypes = pcRequiredTypes ctx,+        pcOutput = pcOutput ctx,+        pcDisallowInit = pcDisallowInit ctx,+        pcLoopSetup = pcLoopSetup ctx,+        pcCleanupSetup = pcCleanupSetup ctx,+        pcInCleanup = pcInCleanup ctx,+        pcExprMap = pcExprMap ctx,+        pcReservedMacros = ((n,c):pcReservedMacros ctx),+        pcNoTrace = pcNoTrace ctx+      }+  ccReleaseExprMacro ctx _ n =+    return $ ProcedureContext {+        pcScope = pcScope ctx,+        pcType = pcType ctx,+        pcExtParams = pcExtParams ctx,+        pcIntParams = pcIntParams ctx,+        pcMembers = pcMembers ctx,+        pcCategories = pcCategories ctx,+        pcAllFilters = pcAllFilters ctx,+        pcExtFilters = pcExtFilters ctx,+        pcIntFilters = pcIntFilters ctx,+        pcParamScopes = pcParamScopes ctx,+        pcFunctions = pcFunctions ctx,+        pcVariables = pcVariables ctx,+        pcReturns = pcReturns ctx,+        pcJumpType = pcJumpType ctx,+        pcIsNamed = pcIsNamed ctx,+        pcPrimNamed = pcPrimNamed ctx,+        pcRequiredTypes = pcRequiredTypes ctx,+        pcOutput = pcOutput ctx,+        pcDisallowInit = pcDisallowInit ctx,+        pcLoopSetup = pcLoopSetup ctx,+        pcCleanupSetup = pcCleanupSetup ctx,+        pcInCleanup = pcInCleanup ctx,+        pcExprMap = pcExprMap ctx,+        pcReservedMacros = filter ((/= n) . fst) $ pcReservedMacros ctx,+        pcNoTrace = pcNoTrace ctx+      }   ccSetNoTrace ctx t =     return $ ProcedureContext {         pcScope = pcScope ctx,@@ -602,6 +680,7 @@         pcCleanupSetup = pcCleanupSetup ctx,         pcInCleanup = pcInCleanup ctx,         pcExprMap = pcExprMap ctx,+        pcReservedMacros = pcReservedMacros ctx,         pcNoTrace = t       }   ccGetNoTrace = return . pcNoTrace
src/Compilation/ScopeContext.hs view
@@ -102,7 +102,7 @@       fa' <- fmap (Map.union fa) $ getFilterMap pi2 fi2       mapErrorsM_ (checkFilter r fa') fi2     checkFilter r fa (ParamFilter c2 n2 f) =-      validateTypeFilter r fa f <?? ("In " ++ show n2 ++ " " ++ show f ++ formatFullContextBrace c2)+      validateTypeFilter r fa f <?? "In " ++ show n2 ++ " " ++ show f ++ formatFullContextBrace c2     checkFunction pm f =       when (sfScope f == ValueScope) $         mapErrorsM_ (checkParam pm) $ pValues $ sfParams f
src/CompilerCxx/Category.hs view
@@ -16,6 +16,7 @@  -- Author: Kevin P. Barry [ta0kira@gmail.com] +{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE Safe #-} @@ -29,7 +30,7 @@   compileConcreteTemplate,   compileInterfaceDefinition,   compileModuleMain,-  compileTestMain,+  compileTestsModule, ) where  import Control.Monad (foldM,when)@@ -38,6 +39,11 @@ import qualified Data.Map as Map import qualified Data.Set as Set +#if MIN_VERSION_base(4,11,0)+#else+import Data.Semigroup+#endif+ import Base.CompileError import Base.MergeTree import Compilation.CompilerState@@ -63,17 +69,17 @@     coCategory :: Maybe CategoryName,     coFilename :: String,     coNamespace :: Namespace,-    coUsesNamespace :: [Namespace],-    coUsesCategory :: [CategoryName],+    coUsesNamespace :: Set.Set Namespace,+    coUsesCategory :: Set.Set CategoryName,     coOutput :: [String]   }   deriving (Show)  data LanguageModule c =   LanguageModule {-    lmPublicNamespaces :: [Namespace],-    lmPrivateNamespaces :: [Namespace],-    lmLocalNamespaces :: [Namespace],+    lmPublicNamespaces :: Set.Set Namespace,+    lmPrivateNamespaces :: Set.Set Namespace,+    lmLocalNamespaces :: Set.Set Namespace,     lmPublicDeps :: [AnyCategory c],     lmPrivateDeps :: [AnyCategory c],     lmTestingDeps :: [AnyCategory c],@@ -115,8 +121,8 @@     tmPublic  = foldM includeNewTypes defaultCategories [cs0,cs1]     tmPrivate = tmPublic  >>= \tm -> foldM includeNewTypes tm [ps0,ps1]     tmTesting = tmPrivate >>= \tm -> foldM includeNewTypes tm [ts0,ts1]-    nsPublic = ns0 ++ ns2-    nsPrivate = nsPublic ++ ns1+    nsPublic = ns0 `Set.union` ns2+    nsPrivate = ns1 `Set.union` nsPublic     nsTesting = nsPrivate     compileSourceP testing tm ns c = do       tm' <- tm@@ -147,7 +153,7 @@       hxx <- mapErrorsM (compileCategoryDeclaration testing tm' ns4) cs2       let interfaces = filter (not . isValueConcrete) cs2       cxx1 <- mapErrorsM (compileInterfaceDefinition testing) interfaces-      cxx2 <- mapErrorsM (compileDefinition testing tm' (ns:ns4)) ds+      cxx2 <- mapErrorsM (compileDefinition testing tm' (ns `Set.insert` ns4)) ds       return (ds,hxx ++ cxx1 ++ cxx2)     mergeGeneratedX ((ds,xx):xs2) = let (ds2,xx2) = mergeGeneratedX xs2 in (ds++ds2,xx++xx2)     mergeGeneratedX _             = ([],[])@@ -190,7 +196,7 @@              ("Category " ++ show (getCategoryName t) ++               formatFullContextBrace (getCategoryContext t) ++               " is defined " ++ show (length ds) ++ " times") !!>-               (mapErrorsM_ (\d -> compileErrorM $ "Defined at " ++ formatFullContext (dcContext d)) ds)+                mapErrorsM_ (\d -> compileErrorM $ "Defined at " ++ formatFullContext (dcContext d)) ds     checkSupefluous es2       | null es2 = return ()       | otherwise = compileErrorM $ "External categories either not concrete or not present: " ++@@ -199,12 +205,29 @@     streamlinedError n =       compileErrorM $ "Category " ++ show n ++ " cannot be streamlined because it was not declared external" +compileTestsModule :: (Show c, CompileErrorM m) =>+  LanguageModule c -> Namespace -> [String] -> [AnyCategory c] -> [DefinedCategory c] ->+  [TestProcedure c] -> m ([CxxOutput],CxxOutput,[(FunctionName,[c])])+compileTestsModule cm ns args cs ds ts = do+  let xs = PrivateSource {+      psNamespace = ns,+      psTesting = True,+      psCategory = cs,+      psDefine = ds+    }+  xx <- compileLanguageModule cm [xs]+  (main,fs) <- compileTestMain cm args xs ts+  return (xx,main,fs)+ compileTestMain :: (Show c, CompileErrorM m) =>-  LanguageModule c -> PrivateSource c -> Expression c -> m CxxOutput-compileTestMain (LanguageModule ns0 ns1 ns2 cs0 ps0 ts0 cs1 ps1 ts1 _ _ em) ts2 e = do+  LanguageModule c -> [String] -> PrivateSource c -> [TestProcedure c] ->+  m (CxxOutput,[(FunctionName,[c])])+compileTestMain (LanguageModule ns0 ns1 ns2 cs0 ps0 ts0 cs1 ps1 ts1 _ _ em) args ts2 tests = do   tm' <- tm-  (req,main) <- createTestFile tm' em e-  return $ CxxOutput Nothing testFilename NoNamespace ([psNamespace ts2]++ns0++ns1++ns2) req main where+  (CompiledData req main) <- createTestFile tm' em args tests+  let output = CxxOutput Nothing testFilename NoNamespace (psNamespace ts2 `Set.insert` Set.unions [ns0,ns1,ns2]) req main+  let tests' = map (\t -> (tpName t,tpContext t)) tests+  return (output,tests') where   tm = foldM includeNewTypes defaultCategories [cs0,cs1,ps0,ps1,ts0,ts1,psCategory ts2]  compileModuleMain :: (Show c, CompileErrorM m) =>@@ -216,22 +239,22 @@   let cs = filter (\c -> getCategoryName c == n) $ concat $ map psCategory xa   tm'' <- includeNewTypes tm' cs   (ns,main) <- createMainFile tm'' em n f-  return $ CxxOutput Nothing mainFilename NoNamespace ([ns]++ns0++ns1++ns2) [n] main where+  return $ CxxOutput Nothing mainFilename NoNamespace (ns `Set.insert` Set.unions [ns0,ns1,ns2]) (Set.fromList [n]) main where     tm = foldM includeNewTypes defaultCategories [cs0,cs1,ps0,ps1]     reconcile [_] = return ()     reconcile []  = compileErrorM $ "No matches for main category " ++ show n ++ " ($TestsOnly$ sources excluded)"     reconcile ds  =-      ("Multiple matches for main category " ++ show n) !!>+      "Multiple matches for main category " ++ show n !!>         mapErrorsM_ (\d -> compileErrorM $ "Defined at " ++ formatFullContext (dcContext d)) ds  compileCategoryDeclaration :: (Show c, CompileErrorM m) =>-  Bool -> CategoryMap c -> [Namespace] -> AnyCategory c -> m CxxOutput+  Bool -> CategoryMap c -> Set.Set Namespace -> AnyCategory c -> m CxxOutput compileCategoryDeclaration testing _ ns t =   return $ CxxOutput (Just $ getCategoryName t)                      (headerFilename name)                      (getCategoryNamespace t)-                     (ns ++ [getCategoryNamespace t])-                     (Set.toList $ cdRequired file)+                     (getCategoryNamespace t `Set.insert` ns)+                     (cdRequired file)                      (cdOutput file) where     file = mconcat $ [         CompiledData depends [],@@ -265,7 +288,7 @@ compileInterfaceDefinition :: CompileErrorM m => Bool -> AnyCategory c -> m CxxOutput compileInterfaceDefinition testing t = do   te <- typeConstructor-  commonDefineAll testing t [] Nothing emptyCode emptyCode emptyCode te []+  commonDefineAll testing t Set.empty Nothing emptyCode emptyCode emptyCode te []   where     typeConstructor = do       let ps = map vpParam $ getCategoryParams t@@ -281,7 +304,7 @@   Bool -> CategoryMap c -> CategoryName -> m CxxOutput compileConcreteTemplate testing ta n = do   (_,t) <- getConcreteCategory ta ([],n)-  compileConcreteDefinition testing ta Map.empty [] Nothing (defined t) <?? ("In generated template for " ++ show n) where+  compileConcreteDefinition testing ta Map.empty Set.empty Nothing (defined t) <?? "In generated template for " ++ show n where     defined t = DefinedCategory {         dcContext = [],         dcName = getCategoryName t,@@ -311,7 +334,7 @@  compileConcreteStreamlined :: (Show c, CompileErrorM m) =>   Bool -> CategoryMap c -> CategoryName -> m [CxxOutput]-compileConcreteStreamlined testing ta n =  ("In streamlined compilation of " ++ show n) ??> do+compileConcreteStreamlined testing ta n =  "In streamlined compilation of " ++ show n ??> do   (_,t) <- getConcreteCategory ta ([],n)   let guard = if testing                  then testsOnlySourceGuard@@ -320,19 +343,19 @@   let hxx = CxxOutput (Just $ getCategoryName t)                       (headerStreamlined $ getCategoryName t)                       (getCategoryNamespace t)-                      [getCategoryNamespace t]-                      (getCategoryMentions t)+                      (Set.fromList [getCategoryNamespace t])+                      (Set.fromList $ getCategoryMentions t)                       guard   let cxx = CxxOutput (Just $ getCategoryName t)                       (sourceStreamlined $ getCategoryName t)                       (getCategoryNamespace t)-                      [getCategoryNamespace t]-                      (getCategoryMentions t)+                      (Set.fromList [getCategoryNamespace t])+                      (Set.fromList $ getCategoryMentions t)                       []   return [hxx,cxx]  compileConcreteDefinition :: (Show c, CompileErrorM m) =>-  Bool -> CategoryMap c -> ExprMap c -> [Namespace] -> Maybe [ValueRefine c] ->+  Bool -> CategoryMap c -> ExprMap c -> Set.Set Namespace -> Maybe [ValueRefine c] ->   DefinedCategory c -> m CxxOutput compileConcreteDefinition testing ta em ns rs dd@(DefinedCategory c n pi _ _ fi ms _ fs) = do   (_,t) <- getConcreteCategory ta (c,n)@@ -413,7 +436,7 @@       concatM [           return $ onlyCode $ categoryName n ++ "()" ++ initColon ++ initMembersStr ++ " {",           return $ indentCompiled $ onlyCodes $ getCycleCheck (categoryName n),-          return $ indentCompiled $ onlyCode $ startFunctionTracing $ show n ++ " (init @category)",+          return $ indentCompiled $ onlyCode $ startInitTracing n CategoryScope,           return $ onlyCode "}",           return $ clearCompiled initMembers -- Inherit required types.         ]@@ -430,7 +453,7 @@       concatM [           return $ onlyCode $ typeName n ++ "(" ++ allArgs ++ ") : " ++ allInit ++ " {",           return $ indentCompiled $ onlyCodes $ getCycleCheck (typeName n),-          return $ indentCompiled $ onlyCode $ startFunctionTracing $ show n ++ " (init @type)",+          return $ indentCompiled $ onlyCode $ startInitTracing n TypeScope,           return $ indentCompiled $ initMembers,           return $ onlyCode "}"         ]@@ -447,11 +470,11 @@     unwrappedArg i m = writeStoredVariable (dmType m) (UnwrappedSingle $ "args.At(" ++ show i ++ ")")     createMember r filters m = do       validateGeneralInstance r filters (vtType $ dmType m) <??-        ("In creation of " ++ show (dmName m) ++ " at " ++ formatFullContext (dmContext m))+        "In creation of " ++ show (dmName m) ++ " at " ++ formatFullContext (dmContext m)       return $ onlyCode $ variableStoredType (dmType m) ++ " " ++ variableName (dmName m) ++ ";"     createMemberLazy r filters m = do       validateGeneralInstance r filters (vtType $ dmType m) <??-        ("In creation of " ++ show (dmName m) ++ " at " ++ formatFullContext (dmContext m))+        "In creation of " ++ show (dmName m) ++ " at " ++ formatFullContext (dmContext m)       return $ onlyCode $ variableLazyType (dmType m) ++ " " ++ variableName (dmName m) ++ ";"     categoryDispatch fs2 =       return $ onlyCodes $ [@@ -481,7 +504,7 @@       | otherwise = []  commonDefineAll :: CompileErrorM m =>-  Bool -> AnyCategory c -> [Namespace] -> Maybe [ValueRefine c] ->+  Bool -> AnyCategory c -> Set.Set Namespace -> Maybe [ValueRefine c] ->   CompiledData [String] -> CompiledData [String] -> CompiledData [String] ->   CompiledData [String] -> [ScopedFunction c] -> m CxxOutput commonDefineAll testing t ns rs top bottom ce te fe = do@@ -503,8 +526,8 @@   return $ CxxOutput (Just $ getCategoryName t)                      filename                      (getCategoryNamespace t)-                     ((getCategoryNamespace t):ns)-                     (Set.toList req)+                     (getCategoryNamespace t `Set.insert` ns)+                     req                      (guard ++ baseSourceIncludes ++ includes ++ out)   where     conditionalContent@@ -798,34 +821,41 @@       "}"     ] -createMainCommon :: String -> CompiledData [String] -> [String]-createMainCommon n (CompiledData req out) =-  baseSourceIncludes ++ mainSourceIncludes ++ depIncludes req ++ [+createMainCommon :: String -> CompiledData [String] -> CompiledData [String] -> [String]+createMainCommon n (CompiledData req0 out0) (CompiledData req1 out1) =+  baseSourceIncludes ++ mainSourceIncludes ++ depIncludes (req0 `Set.union` req1) ++ out0 ++ [       "int main(int argc, const char** argv) {",       "  SetSignalHandler();",-      "  ProgramArgv program_argv(argc, argv);",-      "  " ++ startFunctionTracing n-    ] ++ out ++ ["}"] where+      "  " ++ startFunctionTracing CategoryNone (FunctionName n)+    ] ++ map ("  " ++) out1 ++ ["}"] where       depIncludes req2 = map (\i -> "#include \"" ++ headerFilename i ++ "\"") $                            Set.toList req2  createMainFile :: (Show c, CompileErrorM m) =>   CategoryMap c -> ExprMap c -> CategoryName -> FunctionName -> m (Namespace,[String])-createMainFile tm em n f = ("In the creation of the main binary procedure") ??> do-  ca <- fmap indentCompiled (compileMainProcedure tm em expr)-  let file = noTestsOnlySourceGuard ++ createMainCommon "main" ca+createMainFile tm em n f = "In the creation of the main binary procedure" ??> do+  ca <- compileMainProcedure tm em expr+  let file = noTestsOnlySourceGuard ++ createMainCommon "main" emptyCode (argv <> ca)   (_,t) <- getConcreteCategory tm ([],n)   return (getCategoryNamespace t,file) where     funcCall = FunctionCall [] f (Positional []) (Positional [])     mainType = JustTypeInstance $ TypeInstance n (Positional [])     expr = Expression [] (TypeCall [] mainType funcCall) []+    argv = onlyCode "ProgramArgv program_argv(argc, argv);"  createTestFile :: (Show c, CompileErrorM m) =>-  CategoryMap c -> ExprMap c  -> Expression c -> m ([CategoryName],[String])-createTestFile tm em e = ("In the creation of the test binary procedure") ??> do-  ca@(CompiledData req _) <- fmap indentCompiled (compileMainProcedure tm em e)-  let file = testsOnlySourceGuard ++ createMainCommon "test" ca-  return (Set.toList req,file)+  CategoryMap c -> ExprMap c  -> [String] -> [TestProcedure c] -> m (CompiledData [String])+createTestFile tm em args ts = "In the creation of the test binary procedure" ??> do+  ts' <- fmap mconcat $ mapErrorsM (compileTestProcedure tm em) ts+  (include,sel) <- selectTestFromArgv1 $ map tpName ts+  let (CompiledData req _) = ts' <> sel+  let file = testsOnlySourceGuard ++ createMainCommon "testcase" (onlyCodes include <> ts') (argv <> sel)+  return $ CompiledData req file where+    args' = map escapeChars args+    argv = onlyCodes [+        "const char* argv2[] = { \"testcase\" " ++ concat (map (", " ++) args') ++ " };",+        "ProgramArgv program_argv(sizeof argv2 / sizeof(char*), argv2);"+      ]  getCategoryMentions :: AnyCategory c -> [CategoryName] getCategoryMentions t = fromRefines (getCategoryRefines t) ++
src/CompilerCxx/CategoryContext.hs view
@@ -82,6 +82,7 @@       pcCleanupSetup = [],       pcInCleanup = False,       pcExprMap = em,+      pcReservedMacros = [],       pcNoTrace = False     } @@ -143,6 +144,7 @@       pcCleanupSetup = [],       pcInCleanup = False,       pcExprMap = em,+      pcReservedMacros = [],       pcNoTrace = False     }   where@@ -173,5 +175,6 @@     pcCleanupSetup = [],     pcInCleanup = False,     pcExprMap = em,+    pcReservedMacros = [],     pcNoTrace = False   }
src/CompilerCxx/Code.hs view
@@ -41,6 +41,8 @@   showCreationTrace,   startCleanupTracing,   startFunctionTracing,+  startInitTracing,+  startTestTracing,   testsOnlyCategoryGuard,   testsOnlySourceGuard,   typeBase,@@ -85,8 +87,15 @@ clearCompiled :: CompiledData [String] -> CompiledData [String] clearCompiled (CompiledData r _) = CompiledData r [] -startFunctionTracing :: String -> String-startFunctionTracing f = "TRACE_FUNCTION(" ++ show f ++ ")"+startFunctionTracing :: CategoryName -> FunctionName -> String+startFunctionTracing CategoryNone f = "TRACE_FUNCTION(" ++ show (show f) ++ ")"+startFunctionTracing t            f = "TRACE_FUNCTION(" ++ show (show t ++ "." ++ show f) ++ ")"++startInitTracing :: CategoryName -> SymbolScope -> String+startInitTracing t s = "TRACE_FUNCTION(" ++ show (show t ++ " " ++ show s ++ " init") ++ ")"++startTestTracing :: FunctionName -> String+startTestTracing f = "TRACE_FUNCTION(" ++ show ("unittest " ++ show f) ++ ")"  startCleanupTracing :: String startCleanupTracing = "TRACE_CLEANUP"
src/CompilerCxx/Naming.hs view
@@ -45,6 +45,7 @@   sourceStreamlined,   tableName,   testFilename,+  testFunctionName,   typeCreator,   typeGetter,   typeName,@@ -133,6 +134,9 @@  collectionName :: CategoryName -> String collectionName n = "Functions_" ++ show n++testFunctionName :: FunctionName -> String+testFunctionName f = "Test_" ++ show f  tableName :: CategoryName -> String tableName n = "Table_" ++ show n
src/CompilerCxx/Procedure.hs view
@@ -29,6 +29,8 @@   compileMainProcedure,   compileLazyInit,   compileRegularInit,+  compileTestProcedure,+  selectTestFromArgv1, ) where  import Control.Applicative ((<|>))@@ -77,7 +79,7 @@       unreachable <- csIsUnreachable       when (not unreachable) $         doImplicitReturn [] <???-          ("In implicit return from " ++ show n ++ formatFullContextBrace c)+          "In implicit return from " ++ show n ++ formatFullContextBrace c     wrapProcedure output pt ct =       mconcat [           onlyCode header2,@@ -117,7 +119,7 @@     returnType = "ReturnTuple"     setProcedureTrace       | any isNoTrace pragmas = return []-      | otherwise             = return [startFunctionTracing $ show t ++ "." ++ show n]+      | otherwise             = return [startFunctionTracing t n]     setCreationTrace       | not $ any isTraceCreation pragmas = return []       | s /= ValueScope =@@ -152,7 +154,7 @@      then return e'      else return $ predTraceContext c ++ e'   where-    compile = ("In condition at " ++ formatFullContext c) ???> do+    compile = "In condition at " ++ formatFullContext c ???> do       (ts,e') <- compileExpression e       lift $ checkCondition ts       return $ useAsUnboxed PrimBool e'@@ -203,7 +205,7 @@       autoPositionalCleanup e     -- Multi-expression => must all be singles.     getReturn rs = do-      (lift $ mapErrorsM_ checkArity $ zip ([0..] :: [Int]) $ map (fst . snd) rs) <???+      lift (mapErrorsM_ checkArity $ zip ([0..] :: [Int]) $ map (fst . snd) rs) <???         ("In return at " ++ formatFullContext c)       csRegisterReturn c $ Just $ Positional $ map (head . pValues . fst . snd) rs       let e = OpaqueMulti $ "ReturnTuple(" ++ intercalate "," (map (useAsUnwrapped . snd . snd) rs) ++ ")"@@ -243,7 +245,7 @@   r <- csResolver   fa <- csAllFilters   lift $ (checkValueAssignment r fa t0 formattedRequiredValue) <??-    ("In fail call at " ++ formatFullContext c)+    "In fail call at " ++ formatFullContext c   csSetJumpType JumpFailCall   maybeSetTrace c   csWrite ["BUILTIN_FAIL(" ++ useAsUnwrapped e0 ++ ")"]@@ -274,14 +276,14 @@       return t     getVariableType (ExistingVariable (DiscardInput _)) t = return t     createVariable r fa (CreateVariable c2 t1 n) t2 =-      ("In creation of " ++ show n ++ " at " ++ formatFullContext c2) ???> do+      "In creation of " ++ show n ++ " at " ++ formatFullContext c2 ???> do         -- TODO: Call csRequiresTypes for t1. (Maybe needs a helper function.)         lift $ collectAllM_ [validateGeneralInstance r fa (vtType t1),                              checkValueAssignment 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 =-      ("In assignment to " ++ show n ++ " at " ++ formatFullContext c2) ???> do+      "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@@ -328,7 +330,7 @@   fa <- csAllFilters   let Positional [t2] = ts   lift $ (checkValueAssignment r fa t2 t1) <??-    ("In initialization of " ++ show n ++ " at " ++ formatFullContext c)+    "In initialization of " ++ show n ++ " at " ++ formatFullContext c   csWrite [variableName n ++ "([this]() { return " ++ writeStoredVariable t1 e' ++ "; })"]  compileVoidExpression :: (Show c, CompileErrorM m,@@ -426,7 +428,7 @@     case cl of          Just p2@(Procedure c _) -> do            ctxCl0' <- lift $ ccStartCleanup ctxCl0-           ctxCl <- compileProcedure ctxCl0' p2 <??? ("In cleanup starting at " ++ formatFullContext c)+           ctxCl <- compileProcedure ctxCl0' p2 <??? "In cleanup starting at " ++ formatFullContext c            p2' <- lift $ ccGetOutput ctxCl            noTrace <- csGetNoTrace            let p2'' = if noTrace@@ -453,7 +455,7 @@   where     createVariable r fa (c,t,n) = do       lift $ validateGeneralInstance r fa (vtType t) <??-        ("In creation of " ++ show n ++ " at " ++ formatFullContext c)+        "In creation of " ++ show n ++ " at " ++ formatFullContext c       csWrite [variableStoredType t ++ " " ++ variableName n ++ ";"]     showVariable (c,t,n) = do       -- TODO: Call csRequiresTypes for t. (Maybe needs a helper function.)@@ -576,7 +578,7 @@       -- Multi-expression => must all be singles.       getValues rs = do         (mapErrorsM_ checkArity $ zip ([0..] :: [Int]) $ map fst rs) <??-          ("In return at " ++ formatFullContext c)+          "In return at " ++ formatFullContext c         return (map (head . pValues . fst) rs,                 "ArgTuple(" ++ intercalate ", " (map (useAsUnwrapped . snd) rs) ++ ")")       checkArity (_,Positional [_]) = return ()@@ -658,7 +660,7 @@     fa <- csAllFilters     let vt = ValueType RequiredValue $ singleType $ JustTypeInstance t     (lift $ checkValueAssignment r fa t' vt) <???-      ("In converted call at " ++ formatFullContext c)+      "In converted call at " ++ formatFullContext c     f' <- lookupValueFunction vt f     compileFunctionCall (Just $ useAsUnwrapped e') f' f   transform e (ValueCall c f) = do@@ -694,7 +696,11 @@   return (Positional [t],readStoredVariable lazy t (scoped ++ variableName n)) compileExpressionStart (NamedMacro c n) = do   e <- csExprLookup c n-  compileExpression e <??? ("In env lookup at " ++ formatFullContext c)+  csReserveExprMacro c n+  e' <- compileExpression e <??? "In expansion of " ++ show n ++ " at " ++ formatFullContext c+  -- NOTE: This will be skipped if expression compilation fails.+  csReleaseExprMacro c n+  return e' compileExpressionStart (CategoryCall c t f@(FunctionCall _ n _ _)) = do   f' <- csGetCategoryFunction c (Just t) n   csRequiresTypes $ Set.fromList [t,sfType f']@@ -703,7 +709,7 @@ compileExpressionStart (TypeCall c t f@(FunctionCall _ n _ _)) = do   r <- csResolver   fa <- csAllFilters-  lift $ validateGeneralInstance r fa (singleType t) <?? ("In function call at " ++ formatFullContext c)+  lift $ validateGeneralInstance r fa (singleType t) <?? "In function call at " ++ formatFullContext c   f' <- csGetTypeFunction c (Just $ singleType t) n   when (sfScope f' /= TypeScope) $ lift $ compileErrorM $ "Function " ++ show n ++                                           " cannot be used as a type function" ++@@ -755,7 +761,7 @@   lift $ validateGeneralInstance r fa t1   lift $ validateGeneralInstance r fa t2   lift $ (checkValueAssignment r fa t0 (ValueType OptionalValue t1)) <??-    ("In argument to reduce call at " ++ formatFullContext c)+    "In argument to reduce call at " ++ formatFullContext c   -- TODO: If t1 -> t2 then just return e without a Reduce call.   t1' <- expandGeneralInstance t1   t2' <- expandGeneralInstance t2@@ -813,7 +819,7 @@   r <- csResolver   fa <- csAllFilters   lift $ (checkValueAssignment r fa t t0) <??-    ("In assignment at " ++ formatFullContext c)+    "In assignment at " ++ formatFullContext c   csUpdateAssigned n   scoped <- autoScope s   let lazy = s == CategoryScope@@ -875,13 +881,13 @@     -- Multi-expression => must all be singles.     getValues rs = do       (mapErrorsM_ checkArity $ zip ([0..] :: [Int]) $ map fst rs) <??-        ("In return at " ++ formatFullContext c)+        "In return at " ++ formatFullContext c       return (map (head . pValues . fst) rs, "ArgTuple(" ++ intercalate ", " (map (useAsUnwrapped . snd) rs) ++ ")")     checkArity (_,Positional [_]) = return ()     checkArity (i,Positional ts)  =       compileErrorM $ "Return position " ++ show i ++ " has " ++ show (length ts) ++ " values but should have 1"     checkArg r fa t0 (i,t1) = do-      checkValueAssignment r fa t1 t0 <?? ("In argument " ++ show i ++ " to " ++ show (sfName f))+      checkValueAssignment r fa t1 t0 <?? "In argument " ++ show i ++ " to " ++ show (sfName f)  guessParamsFromArgs :: (Show c, CompileErrorM m, TypeResolver r) =>   r -> ParamFilters -> ScopedFunction c -> Positional (InstanceOrInferred c) ->@@ -911,6 +917,50 @@     compiler = do       ctx0 <- getCleanContext       compileProcedure ctx0 procedure >>= put++compileTestProcedure :: (Show c, CompileErrorM m) =>+  CategoryMap c -> ExprMap c -> TestProcedure c -> m (CompiledData [String])+compileTestProcedure tm em (TestProcedure c n p) = do+  ctx <- getMainContext tm em+  p' <- runDataCompiler compiler ctx <??+    "In unittest " ++ show n ++ formatFullContextBrace c+  return $ mconcat [+      onlyCode $ "ReturnTuple " ++ testFunctionName n ++ "() {",+      indentCompiled $ onlyCode $ startTestTracing n,+      indentCompiled p',+      indentCompiled $ onlyCode $ "return ReturnTuple();",+      onlyCode "}"+    ] where+    compiler = do+      ctx0 <- getCleanContext+      compileProcedure ctx0 p >>= put++selectTestFromArgv1 :: CompileErrorM m => [FunctionName] -> m ([String],CompiledData [String])+selectTestFromArgv1 fs = return (includes,allCode) where+  allCode = mconcat [+      initMap,+      selectFromMap+    ]+  initMap = onlyCodes $ [+      "const std::unordered_map<std::string, ReturnTuple(*)()> tests{"+    ] ++ map (("  " ++) . testEntry) fs ++ [+      "};"+    ]+  selectFromMap = onlyCodes [+      "if (argc < 2) FAIL() << argv[0] << \" [unittest name]\";",+      "const auto name = argv[1];",+      "const auto test = tests.find(name);",+      "if (test != tests.end()) {",+      "  (void) (*test->second)();",+      " } else {",+      "  FAIL() << argv[0] << \": unittest \" << name << \" does not exist\";",+      "}"+    ]+  testEntry f = "{ \"" ++ show f ++ "\", &" ++ testFunctionName f ++ " },"+  includes = [+      "#include <string>",+      "#include <unordered_map>"+    ]  autoScope :: CompilerContext c m s a =>   SymbolScope -> CompilerState a m String
src/Config/LocalConfig.hs view
@@ -79,13 +79,13 @@ instance CompilerBackend Backend where   runCxxCommand (UnixBackend cb co ab) (CompileToObject s p ms ps e) = do     objName <- errorFromIO $ canonicalizePath $ p </> (takeFileName $ dropExtension s ++ ".o")-    executeProcess cb (co ++ otherOptions ++ ["-c", s, "-o", objName]) <?? ("In compilation of " ++ s)+    executeProcess cb (co ++ otherOptions ++ ["-c", s, "-o", objName]) <?? "In compilation of " ++ s     if e       then do         -- Extra files are put into .a since they will be unconditionally         -- included. This prevents unwanted symbol dependencies.         arName  <- errorFromIO $ canonicalizePath $ p </> (takeFileName $ dropExtension s ++ ".a")-        executeProcess ab ["-q",arName,objName] <?? ("In packaging of " ++ objName)+        executeProcess ab ["-q",arName,objName] <?? "In packaging of " ++ objName         return arName       else return objName where       otherOptions = map (("-I" ++) . normalise) ps ++ map macro ms@@ -94,10 +94,10 @@   runCxxCommand (UnixBackend cb co _) (CompileToBinary m ss o ps lf) = do     let arFiles    = filter (isSuffixOf ".a")       ss     let otherFiles = filter (not . isSuffixOf ".a") ss-    executeProcess cb (co ++ otherOptions ++ m:otherFiles ++ arFiles ++ ["-o", o]) <?? ("In linking of " ++ o)+    executeProcess cb (co ++ otherOptions ++ m:otherFiles ++ arFiles ++ ["-o", o]) <?? "In linking of " ++ o     return o where       otherOptions = lf ++ map ("-I" ++) (map normalise ps)-  runTestCommand _ (TestCommand b p) = errorFromIO $ do+  runTestCommand _ (TestCommand b p as) = errorFromIO $ do     (outF,outH) <- mkstemps "/tmp/ztest_" ".txt"     (errF,errH) <- mkstemps "/tmp/ztest_" ".txt"     pid <- forkProcess (execWithCapture outH errH)@@ -116,7 +116,7 @@         when (not $ null p) $ setCurrentDirectory p         hDuplicateTo h1 stdout         hDuplicateTo h2 stderr-        executeFile b True [] Nothing+        executeFile b True as Nothing   getCompilerHash b = VersionHash $ flip showHex "" $ abs $ hash $ minorVersion ++ show b where     minorVersion = show $ take 3 $ versionBranch version @@ -141,7 +141,8 @@        then return False        else do          ps2 <- errorFromIO $ potentialSystemPaths r m-         errorFromIO (findModule ps2) >>= return . not . isJust+         path <- errorFromIO (findModule ps2)+         return $ isJust path   resolveBaseModule _ = do     let m = "base"     m0 <- errorFromIO $ getDataFileName m
src/Module/CompileMetadata.hs view
@@ -32,6 +32,7 @@  import Cli.CompileOptions import Cli.Programs (VersionHash)+import Types.Pragma (MacroName) import Types.Procedure (Expression) import Types.TypeCategory (Namespace) import Types.TypeInstance (CategoryName)@@ -95,7 +96,7 @@   ModuleConfig {     mcRoot :: FilePath,     mcPath :: FilePath,-    mcExprMap :: [(String,Expression SourcePos)],+    mcExprMap :: [(MacroName,Expression SourcePos)],     mcPublicDeps :: [FilePath],     mcPrivateDeps :: [FilePath],     mcExtraFiles :: [ExtraSource],
src/Module/ParseMetadata.hs view
@@ -22,9 +22,9 @@   autoWriteConfig, ) where +import Control.Applicative.Permutations import Control.Monad (when) import Text.Parsec-import Text.Parsec.String  import Base.CompileError import Cli.CompileOptions@@ -32,32 +32,29 @@ import Module.CompileMetadata import Parser.Common import Parser.Procedure ()-import Parser.Pragma (parseMacroName) import Parser.TypeCategory () import Parser.TypeInstance () import Text.Regex.TDFA -- Not safe!+import Types.Pragma (MacroName) import Types.Procedure (Expression) import Types.TypeCategory (FunctionName(..),Namespace(..)) import Types.TypeInstance (CategoryName(..))   class ConfigFormat a where-  readConfig :: Parser a+  readConfig :: CompileErrorM m => ParserE m a   writeConfig :: CompileErrorM m => a -> m [String]  autoReadConfig :: (ConfigFormat a, CompileErrorM m) => String -> String -> m a-autoReadConfig f s  = unwrap parsed where-  parsed = parse (between optionalSpace endOfDoc readConfig) f s-  unwrap (Left e)  = compileErrorM (show e)-  unwrap (Right t) = return t+autoReadConfig f s = runParserE (between optionalSpace endOfDoc readConfig) f s  autoWriteConfig ::  (ConfigFormat a, CompileErrorM m) => a -> m String autoWriteConfig = fmap unlines . writeConfig -structOpen :: Parser ()+structOpen :: Monad m => ParserE m () structOpen = sepAfter (string_ "{") -structClose :: Parser ()+structClose :: Monad m => ParserE m () structClose = sepAfter (string_ "}")  indents :: [String] -> [String]@@ -75,23 +72,17 @@     when (not $ show c =~ "^[A-Z][A-Za-z0-9]*$") $       compileErrorM $ "Invalid category name: \"" ++ show c ++ "\"" -parseCategoryName :: Parser CategoryName-parseCategoryName = sourceParser :: Parser CategoryName- validateFunctionName :: CompileErrorM m => FunctionName -> m () validateFunctionName f =     when (not $ show f =~ "^[a-z][A-Za-z0-9]*$") $       compileErrorM $ "Invalid function name: \"" ++ show f ++ "\"" -parseFunctionName :: Parser FunctionName-parseFunctionName = sourceParser :: Parser FunctionName- validateHash :: CompileErrorM m => VersionHash -> m () validateHash h =     when (not $ show h =~ "^[A-Za-z0-9]+$") $       compileErrorM $ "Version hash must be a hex string: \"" ++ show h ++ "\"" -parseHash :: Parser VersionHash+parseHash :: Monad m => ParserE m VersionHash parseHash = labeled "version hash" $ sepAfter (fmap VersionHash $ many1 hexDigit)  maybeShowNamespace :: CompileErrorM m => String -> Namespace -> m [String]@@ -101,55 +92,56 @@   return [l ++ " " ++ ns] maybeShowNamespace _ _ = return [] -parseNamespace :: Parser Namespace+parseNamespace :: Monad m => ParserE m Namespace parseNamespace = labeled "namespace" $ do   b <- lower   e <- sepAfter $ many (alphaNum <|> char '_')   return $ StaticNamespace (b:e) -parseQuoted :: Parser String+parseQuoted :: Monad m => ParserE m String parseQuoted = labeled "quoted string" $ do   string_ "\""   ss <- manyTill stringChar (string_ "\"")   optionalSpace   return ss -parseList :: Parser a -> Parser [a]+parseList :: Monad m => ParserE m a -> ParserE m [a] parseList p = labeled "list" $ do   sepAfter (string_ "[")   xs <- manyTill (sepAfter p) (string_ "]")   optionalSpace   return xs -parseOptional :: String -> a -> Parser a -> Parser a-parseOptional l def p = parseRequired l p <|> return def+parseOptional :: Monad m => String -> a -> ParserE m a -> Permutation (ParserE m) a+parseOptional l def p = toPermutationWithDefault def $ do+    try $ sepAfter (string_ l)+    p -parseRequired :: String -> Parser a -> Parser a-parseRequired l p = do+parseRequired :: Monad m => String -> ParserE m a -> Permutation (ParserE m) a+parseRequired l p = toPermutation $ do     try $ sepAfter (string_ l)     p  instance ConfigFormat CompileMetadata where-  readConfig = do-    h   <- parseRequired "version_hash:"       parseHash-    p   <- parseRequired "path:"               parseQuoted-    ns1 <- parseOptional "public_namespace:"   NoNamespace parseNamespace-    ns2 <- parseOptional "private_namespace:"  NoNamespace parseNamespace-    is  <- parseRequired "public_deps:"        (parseList parseQuoted)-    is2 <- parseRequired "private_deps:"       (parseList parseQuoted)-    cs1 <- parseRequired "public_categories:"  (parseList parseCategoryName)-    cs2 <- parseRequired "private_categories:" (parseList parseCategoryName)-    ds1 <- parseRequired "public_subdirs:"     (parseList parseQuoted)-    ds2 <- parseRequired "private_subdirs:"    (parseList parseQuoted)-    ps  <- parseRequired "public_files:"       (parseList parseQuoted)-    xs  <- parseRequired "private_files:"      (parseList parseQuoted)-    ts  <- parseRequired "test_files:"         (parseList parseQuoted)-    hxx <- parseRequired "hxx_files:"          (parseList parseQuoted)-    cxx <- parseRequired "cxx_files:"          (parseList parseQuoted)-    bs  <- parseRequired "binaries:"           (parseList parseQuoted)-    lf  <- parseRequired "link_flags:"         (parseList parseQuoted)-    os  <- parseRequired "object_files:"       (parseList readConfig)-    return (CompileMetadata h p ns1 ns2 is is2 cs1 cs2 ds1 ds2 ps xs ts hxx cxx bs lf os)+  readConfig = runPermutation $ CompileMetadata+    <$> parseRequired "version_hash:"       parseHash+    <*> parseRequired "path:"               parseQuoted+    <*> parseOptional "public_namespace:"   NoNamespace parseNamespace+    <*> parseOptional "private_namespace:"  NoNamespace parseNamespace+    <*> parseRequired "public_deps:"        (parseList parseQuoted)+    <*> parseRequired "private_deps:"       (parseList parseQuoted)+    <*> parseRequired "public_categories:"  (parseList sourceParser)+    <*> parseRequired "private_categories:" (parseList sourceParser)+    <*> parseRequired "public_subdirs:"     (parseList parseQuoted)+    <*> parseRequired "private_subdirs:"    (parseList parseQuoted)+    <*> parseRequired "public_files:"       (parseList parseQuoted)+    <*> parseRequired "private_files:"      (parseList parseQuoted)+    <*> parseRequired "test_files:"         (parseList parseQuoted)+    <*> parseRequired "hxx_files:"          (parseList parseQuoted)+    <*> parseRequired "cxx_files:"          (parseList parseQuoted)+    <*> parseRequired "binaries:"           (parseList parseQuoted)+    <*> parseRequired "link_flags:"         (parseList parseQuoted)+    <*> parseRequired "object_files:"       (parseList readConfig)   writeConfig (CompileMetadata h p ns1 ns2 is is2 cs1 cs2 ds1 ds2 ps xs ts hxx cxx bs lf os) = do     validateHash h     ns1' <- maybeShowNamespace "public_namespace:"  ns1@@ -210,17 +202,19 @@     category = do       sepAfter (string_ "category_object")       structOpen-      c <-  parseRequired "category:" readConfig-      rs <- parseRequired "requires:" (parseList readConfig)-      fs <- parseRequired "files:"    (parseList parseQuoted)+      o <- runPermutation $ CategoryObjectFile+        <$> parseRequired "category:" readConfig+        <*> parseRequired "requires:" (parseList readConfig)+        <*> parseRequired "files:"    (parseList parseQuoted)       structClose-      return (CategoryObjectFile c rs fs)+      return o     other = do       sepAfter (string_ "other_object")       structOpen-      f <- parseRequired "file:" parseQuoted+      f <- runPermutation $ OtherObjectFile+        <$> parseRequired "file:" parseQuoted       structClose-      return (OtherObjectFile f)+      return f   writeConfig (CategoryObjectFile c rs fs) = do     category <- writeConfig c     requires <- fmap concat $ mapErrorsM writeConfig rs@@ -247,17 +241,19 @@     category = do       sepAfter (string_ "category")       structOpen-      c <-  parseRequired "name:"      parseCategoryName-      ns <- parseOptional "namespace:" NoNamespace parseNamespace-      p <-  parseRequired "path:"      parseQuoted+      i <- runPermutation $ CategoryIdentifier+        <$> parseRequired "path:"      parseQuoted+        <*> parseRequired "name:"      sourceParser+        <*> parseOptional "namespace:" NoNamespace parseNamespace       structClose-      return (CategoryIdentifier p c ns)+      return i     unresolved = do       sepAfter (string_ "unresolved")       structOpen-      c <- parseRequired "name:" parseCategoryName+      c <- runPermutation $ UnresolvedCategory+        <$> parseRequired "name:" sourceParser       structClose-      return (UnresolvedCategory c)+      return c   writeConfig (CategoryIdentifier p c ns) = do     validateCategoryName c     namespace <- maybeShowNamespace "namespace:" ns@@ -273,16 +269,15 @@     return $ ["unresolved { " ++ "name: " ++ show c ++ " " ++ "}"]  instance ConfigFormat ModuleConfig where-  readConfig = do-      p   <- parseOptional "root:"           "" parseQuoted-      d   <- parseRequired "path:"              parseQuoted-      em  <- parseOptional "expression_map:" [] (parseList parseExprMacro)-      is  <- parseOptional "public_deps:"    [] (parseList parseQuoted)-      is2 <- parseOptional "private_deps:"   [] (parseList parseQuoted)-      es  <- parseOptional "extra_files:"    [] (parseList readConfig)-      ep  <- parseOptional "include_paths:"  [] (parseList parseQuoted)-      m   <- parseRequired "mode:"              readConfig-      return (ModuleConfig p d em is is2 es ep m)+  readConfig = runPermutation $ ModuleConfig+    <$> parseOptional "root:"           "" parseQuoted+    <*> parseRequired "path:"              parseQuoted+    <*> parseOptional "expression_map:" [] (parseList parseExprMacro)+    <*> parseOptional "public_deps:"    [] (parseList parseQuoted)+    <*> parseOptional "private_deps:"   [] (parseList parseQuoted)+    <*> parseOptional "extra_files:"    [] (parseList readConfig)+    <*> parseOptional "include_paths:"  [] (parseList parseQuoted)+    <*> parseRequired "mode:"              readConfig   writeConfig (ModuleConfig p d em is is2 es ep m) = do     es' <- fmap concat $ mapErrorsM writeConfig es     m' <- writeConfig m@@ -313,11 +308,12 @@     category = do       sepAfter (string_ "category_source")       structOpen-      f <-  parseRequired "source:"        parseQuoted-      cs <- parseOptional "categories:" [] (parseList parseCategoryName)-      ds <- parseOptional "requires:"   [] (parseList parseCategoryName)+      s <- runPermutation $ CategorySource+        <$> parseRequired "source:"        parseQuoted+        <*> parseOptional "categories:" [] (parseList sourceParser)+        <*> parseOptional "requires:"   [] (parseList sourceParser)       structClose-      return (CategorySource f cs ds)+      return s     other = do       f <- parseQuoted       return (OtherSource f)@@ -342,18 +338,20 @@     binary = do       sepAfter (string_ "binary")       structOpen-      c <-  parseRequired "category:"      parseCategoryName-      f <-  parseRequired "function:"      parseFunctionName-      o <-  parseOptional "output:"     "" parseQuoted-      lf <- parseOptional "link_flags:" [] (parseList parseQuoted)+      b <- runPermutation $ CompileBinary+        <$> parseRequired "category:"      sourceParser+        <*> parseRequired "function:"      sourceParser+        <*> parseOptional "output:"     "" parseQuoted+        <*> parseOptional "link_flags:" [] (parseList parseQuoted)       structClose-      return (CompileBinary c f o lf)+      return b     incremental = do       sepAfter (string_ "incremental")       structOpen-      lf <- parseOptional "link_flags:" [] (parseList parseQuoted)+      lf <- runPermutation $ CompileIncremental+        <$> parseOptional "link_flags:" [] (parseList parseQuoted)       structClose-      return (CompileIncremental lf)+      return lf   writeConfig (CompileBinary c f o lf) = do     validateCategoryName c     validateFunctionName f@@ -378,11 +376,12 @@   writeConfig CompileUnspecified = writeConfig (CompileIncremental [])   writeConfig _ = compileErrorM "Invalid compile mode" -parseExprMacro :: Parser (String,Expression SourcePos)+parseExprMacro :: CompileErrorM m => ParserE m (MacroName,Expression SourcePos) parseExprMacro = do   sepAfter (string_ "expression_macro")   structOpen-  n <- parseRequired "name:"       parseMacroName-  e <- parseRequired "expression:" sourceParser+  e <- runPermutation $ (,)+    <$> parseRequired "name:"       sourceParser+    <*> parseRequired "expression:" sourceParser   structClose-  return (n,e)+  return e
src/Module/ProcessMetadata.hs view
@@ -99,8 +99,17 @@   filePresent <- errorFromIO $ doesFileExist f   when (not filePresent) $ compileErrorM $ "Module \"" ++ p ++ "\" has not been configured yet"   c <- errorFromIO $ readFile f-  (autoReadConfig f c) <!!-    ("Could not parse metadata from \"" ++ p ++ "\"; please reconfigure")+  m <- autoReadConfig f c <!!+    "Could not parse metadata from \"" ++ p ++ "\"; please reconfigure"+  p0 <- errorFromIO $ canonicalizePath p+  let p1 = mcRoot m </> mcPath m+  p2 <- errorFromIO $ canonicalizePath $ p0 </> p1+  when (p2 /= p0) $ compileErrorM $ "Expected module path from " ++ f +++                                    " to match " ++ moduleFilename +++                                    " location but got " ++ p2 +++                                    " (resolved from root: \"" ++ mcRoot m +++                                    "\" and path: \"" ++ mcPath m ++ "\")"+  return m  isPathUpToDate :: VersionHash -> ForceMode -> FilePath -> CompileInfoIO Bool isPathUpToDate h f p = do@@ -116,7 +125,7 @@ writeMetadata p m = do   p' <- errorFromIO $ canonicalizePath p   errorFromIO $ hPutStrLn stderr $ "Writing metadata for \"" ++ p' ++ "\"."-  m' <- autoWriteConfig m <?? ("In data for " ++ p)+  m' <- autoWriteConfig m <?? "In data for " ++ p   writeCachedFile p' "" metadataFilename m'  writeRecompile :: FilePath -> ModuleConfig -> CompileInfoIO ()@@ -124,7 +133,7 @@   p' <- errorFromIO $ canonicalizePath p   let f = p </> moduleFilename   errorFromIO $ hPutStrLn stderr $ "Updating config for \"" ++ p' ++ "\"."-  m' <- autoWriteConfig m <?? ("In data for " ++ p)+  m' <- autoWriteConfig m <?? "In data for " ++ p   errorFromIO $ writeFile f m'  eraseCachedData :: FilePath -> CompileInfoIO ()@@ -167,7 +176,7 @@ getExprMap :: FilePath -> ModuleConfig -> CompileInfoIO (ExprMap SourcePos) getExprMap p m = do   path <- errorFromIO $ canonicalizePath (p </> mcRoot m </> mcPath m)-  let defaults = [("MODULE_PATH",Literal (StringLiteral [] path))]+  let defaults = [(MacroName "MODULE_PATH",Literal (StringLiteral [] path))]   return $ Map.fromList $ mcExprMap m ++ defaults  getRealPathsForDeps :: [CompileMetadata] -> [FilePath]@@ -236,7 +245,7 @@           when (cmPath m /= p') $             compileErrorM $ "Module \"" ++ p ++ "\" has an invalid cache path and must be recompiled"           fresh <- errorFromIO $ toCompileInfo $ checkModuleFreshness h cm p m <!!-            ("Module \"" ++ p ++ "\" is out of date and should be recompiled")+            "Module \"" ++ p ++ "\" is out of date and should be recompiled"           if enforce              then fromCompileInfo   fresh              else asCompileWarnings fresh@@ -257,7 +266,7 @@          when (not filePresent) $ compileErrorM $ "Module \"" ++ p ++ "\" has not been compiled yet"          c <- errorFromIO $ readFile f          (autoReadConfig f c) <!!-            ("Could not parse metadata from \"" ++ p ++ "\"; please recompile")+            "Could not parse metadata from \"" ++ p ++ "\"; please recompile"  sortCompiledFiles :: [FilePath] -> ([FilePath],[FilePath],[FilePath]) sortCompiledFiles = foldl split ([],[],[]) where@@ -325,7 +334,7 @@         then return True         else errorFromIO $ doesDirectoryExist f2 -getObjectFileResolver :: [ObjectFile] -> [Namespace] -> [CategoryName] -> [FilePath]+getObjectFileResolver :: [ObjectFile] -> Set.Set Namespace -> Set.Set CategoryName -> [FilePath] getObjectFileResolver os ns ds = resolved ++ nonCategories where   categories    = filter isCategoryObjectFile os   nonCategories = map oofFile $ filter (not . isCategoryObjectFile) os@@ -333,10 +342,10 @@   keyByCategory2 o = ((ciCategory $ cofCategory o,ciNamespace $ cofCategory o),o)   objectMap = Map.fromList $ map keyBySpec categories   keyBySpec o = (cofCategory o,o)-  directDeps = concat $ map resolveDep2 ds+  directDeps = concat $ map resolveDep2 $ Set.toList ds   directResolved = map cofCategory directDeps   resolveDep2 d = unwrap $ foldl (<|>) Nothing allChecks <|> Just [] where-    allChecks = map (\n -> (d,n) `Map.lookup` categoryMap >>= return . (:[])) (ns ++ [NoNamespace])+    allChecks = map (\n -> (d,n) `Map.lookup` categoryMap >>= return . (:[])) (Set.toList ns ++ [NoNamespace])     unwrap (Just xs) = xs     unwrap _         = []   (_,_,resolved) = collectAll Set.empty Set.empty directResolved@@ -369,7 +378,7 @@   cxxToId _                               = undefined   resolveCategory (fs,ca@(CxxOutput _ _ _ ns2 ds _)) =     (cxxToId ca,CategoryObjectFile (cxxToId ca) (filter (/= cxxToId ca) rs) fs) where-      rs = concat $ map (resolveDep categoryMap (ns2 ++ publicNamespaces)) ds+      rs = concat $ map (resolveDep categoryMap (Set.toList ns2 ++ publicNamespaces)) $ Set.toList ds  resolveCategoryDeps :: [CategoryName] -> [CompileMetadata] -> [CategoryIdentifier] resolveCategoryDeps cs deps = resolvedCategories where
src/Parser/Common.hs view
@@ -16,10 +16,12 @@  -- Author: Kevin P. Barry [ta0kira@gmail.com] +{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE Safe #-}  module Parser.Common (   ParseFromSource(..),+  ParserE,   anyComment,   assignOperator,   blockComment,@@ -66,6 +68,7 @@   kwType,   kwTypename,   kwTypes,+  kwUnittest,   kwUpdate,   kwValue,   kwWeak,@@ -80,11 +83,14 @@   nullParse,   operator,   optionalSpace,+  parseAny2,+  parseAny3,   parseBin,   parseDec,   parseHex,   parseOct,   parseSubOne,+  parseErrorM,   pragmaArgsEnd,   pragmaArgsStart,   pragmaEnd,@@ -94,8 +100,10 @@   put22,   put23,   put33,+  quotedString,   regexChar,   requiredSpace,+  runParserE,   sepAfter,   sepAfter1,   sepAfter_,@@ -107,184 +115,204 @@   valueSymbolGet, ) where +import Control.Applicative (empty)+import Control.Monad.Trans (lift) import Data.Char import Data.Foldable import Data.Functor import Data.Monoid import Prelude hiding (foldl,foldr) import Text.Parsec-import Text.Parsec.String import qualified Data.Set as Set +import Base.CompileError ++type ParserE = ParsecT String ()+ class ParseFromSource a where-  -- Should never prune whitespace/comments from front, but always from back.-  sourceParser :: Parser a+  -- Must never prune whitespace/comments from front, but always from back.+  sourceParser :: CompileErrorM m => ParserE m a -labeled :: String -> Parser a -> Parser a+runParserE :: CompileErrorM m => ParserE m a -> String -> String -> m a+runParserE p n s = do+  result <- runPT p () n s+  case result of+       Left e  -> compileErrorM (show e)+       Right t -> return t++parseErrorM :: CompileErrorM m => SourcePos -> String -> ParserE m a+parseErrorM c e = lift $ compileErrorM $ "At " ++ show c ++ ": " ++ e++labeled :: Monad m => String -> ParserE m a -> ParserE m a labeled = flip label -escapeStart :: Parser ()+escapeStart :: Monad m => ParserE m () escapeStart = sepAfter (string_ "\\") -statementStart :: Parser ()+statementStart :: Monad m => ParserE m () statementStart = sepAfter (string_ "\\") -statementEnd :: Parser ()+statementEnd :: Monad m => ParserE m () statementEnd = sepAfter (string_ "") -valueSymbolGet :: Parser ()+valueSymbolGet :: Monad m => ParserE m () valueSymbolGet = sepAfter (string_ ".") -categorySymbolGet :: Parser ()+categorySymbolGet :: CompileErrorM m => ParserE m () categorySymbolGet = labeled ":" $ useNewOperators <|> sepAfter (string_ ":") -typeSymbolGet :: Parser ()+typeSymbolGet :: CompileErrorM m => ParserE m () typeSymbolGet = labeled "." $ useNewOperators <|> sepAfter (string_ ".")  -- TODO: Remove this after a reasonable amount of time.-useNewOperators :: Parser ()+useNewOperators :: CompileErrorM m => ParserE m () useNewOperators = newCategory <|> newType where   newCategory = do+    c <- getPosition     try $ string_ "$$"-    fail "use \":\" instead of \"$$\" to call @category functions"+    parseErrorM c "use \":\" instead of \"$$\" to call @category functions"   newType = do+    c <- getPosition     try $ string_ "$"-    fail "use \".\" instead of \"$\" to call @type functions"+    parseErrorM c "use \".\" instead of \"$\" to call @type functions" -assignOperator :: Parser ()+assignOperator :: Monad m => ParserE m () assignOperator = operator "<-" >> return () -infixFuncStart :: Parser ()+infixFuncStart :: Monad m => ParserE m () infixFuncStart = sepAfter (string_ "`") -infixFuncEnd :: Parser ()+infixFuncEnd :: Monad m => ParserE m () infixFuncEnd = sepAfter (string_ "`")  -- TODO: Maybe this should not use strings.-builtinValues :: Parser String-builtinValues = foldr (<|>) (fail "empty") $ map try [+builtinValues :: Monad m => ParserE m String+builtinValues = foldr (<|>) empty $ map try [     kwSelf >> return "self"   ] -kwAll :: Parser ()+kwAll :: Monad m => ParserE m () kwAll = keyword "all" -kwAllows :: Parser ()+kwAllows :: Monad m => ParserE m () kwAllows = keyword "allows" -kwAny :: Parser ()+kwAny :: Monad m => ParserE m () kwAny = keyword "any" -kwBreak :: Parser ()+kwBreak :: Monad m => ParserE m () kwBreak = keyword "break" -kwCategory :: Parser ()+kwCategory :: Monad m => ParserE m () kwCategory = keyword "@category" -kwCleanup :: Parser ()+kwCleanup :: Monad m => ParserE m () kwCleanup = keyword "cleanup" -kwConcrete :: Parser ()+kwConcrete :: Monad m => ParserE m () kwConcrete = keyword "concrete" -kwContinue :: Parser ()+kwContinue :: Monad m => ParserE m () kwContinue = keyword "continue" -kwDefine :: Parser ()+kwDefine :: Monad m => ParserE m () kwDefine = keyword "define" -kwDefines :: Parser ()+kwDefines :: Monad m => ParserE m () kwDefines = keyword "defines" -kwElif :: Parser ()+kwElif :: Monad m => ParserE m () kwElif = keyword "elif" -kwElse :: Parser ()+kwElse :: Monad m => ParserE m () kwElse = keyword "else" -kwEmpty :: Parser ()+kwEmpty :: Monad m => ParserE m () kwEmpty = keyword "empty" -kwFail :: Parser ()+kwFail :: Monad m => ParserE m () kwFail = keyword "fail" -kwFalse :: Parser ()+kwFalse :: Monad m => ParserE m () kwFalse = keyword "false" -kwIf :: Parser ()+kwIf :: Monad m => ParserE m () kwIf = keyword "if" -kwIn :: Parser ()+kwIn :: Monad m => ParserE m () kwIn = keyword "in" -kwIgnore :: Parser ()+kwIgnore :: Monad m => ParserE m () kwIgnore = keyword "_" -kwInterface :: Parser ()+kwInterface :: Monad m => ParserE m () kwInterface = keyword "interface" -kwOptional :: Parser ()+kwOptional :: Monad m => ParserE m () kwOptional = keyword "optional" -kwPresent :: Parser ()+kwPresent :: Monad m => ParserE m () kwPresent = keyword "present" -kwReduce :: Parser ()+kwReduce :: Monad m => ParserE m () kwReduce = keyword "reduce" -kwRefines :: Parser ()+kwRefines :: Monad m => ParserE m () kwRefines = keyword "refines" -kwRequire :: Parser ()+kwRequire :: Monad m => ParserE m () kwRequire = keyword "require" -kwRequires :: Parser ()+kwRequires :: Monad m => ParserE m () kwRequires = keyword "requires" -kwReturn :: Parser ()+kwReturn :: Monad m => ParserE m () kwReturn = keyword "return" -kwSelf :: Parser ()+kwSelf :: Monad m => ParserE m () kwSelf = keyword "self" -kwScoped :: Parser ()+kwScoped :: Monad m => ParserE m () kwScoped = keyword "scoped" -kwStrong :: Parser ()+kwStrong :: Monad m => ParserE m () kwStrong = keyword "strong" -kwTestcase :: Parser ()+kwTestcase :: Monad m => ParserE m () kwTestcase = keyword "testcase" -kwTrue :: Parser ()+kwTrue :: Monad m => ParserE m () kwTrue = keyword "true" -kwType :: Parser ()+kwType :: Monad m => ParserE m () kwType = keyword "@type" -kwTypename :: Parser ()+kwTypename :: Monad m => ParserE m () kwTypename = keyword "typename" -kwTypes :: Parser ()+kwTypes :: Monad m => ParserE m () kwTypes = keyword "types" -kwUpdate :: Parser ()+kwUnittest :: Monad m => ParserE m ()+kwUnittest = keyword "unittest"++kwUpdate :: Monad m => ParserE m () kwUpdate = keyword "update" -kwValue :: Parser ()+kwValue :: Monad m => ParserE m () kwValue = keyword "@value" -kwWeak :: Parser ()+kwWeak :: Monad m => ParserE m () kwWeak = keyword "weak" -kwWhile :: Parser ()+kwWhile :: Monad m => ParserE m () kwWhile = keyword "while" -operatorSymbol :: Parser Char+operatorSymbol :: Monad m => ParserE m Char operatorSymbol = labeled "operator symbol" $ satisfy (`Set.member` Set.fromList "+-*/%=!<>&|") -isKeyword :: Parser ()+isKeyword :: Monad m => ParserE m () isKeyword = foldr (<|>) nullParse $ map try [     kwAll,     kwAllows,@@ -320,88 +348,89 @@     kwType,     kwTypename,     kwTypes,+    kwUnittest,     kwUpdate,     kwValue,     kwWeak,     kwWhile   ] -nullParse :: Parser ()+nullParse :: Monad m => ParserE m () nullParse = return () -char_ :: Char -> Parser ()+char_ :: Monad m => Char -> ParserE m () char_ = (>> return ()) . char -string_ :: String -> Parser ()+string_ :: Monad m => String -> ParserE m () string_ = (>> return ()) . string -lineEnd :: Parser ()+lineEnd :: Monad m => ParserE m () lineEnd = (endOfLine >> return ()) <|> endOfDoc -lineComment :: Parser String+lineComment :: Monad m => ParserE m String lineComment = between (string_ "//")                       lineEnd                       (many $ satisfy (/= '\n')) -blockComment :: Parser String+blockComment :: Monad m => ParserE m String blockComment = between (string_ "/*")                        (string_ "*/")                        (many $ notFollowedBy (string_ "*/") >> anyChar) -anyComment :: Parser String+anyComment :: Monad m => ParserE m String anyComment = try blockComment <|> try lineComment -optionalSpace :: Parser ()+optionalSpace :: Monad m => ParserE m () optionalSpace = labeled "" $ many (anyComment <|> many1 space) >> nullParse -requiredSpace :: Parser ()+requiredSpace :: Monad m => ParserE m () requiredSpace = labeled "break" $ eof <|> (many1 (anyComment <|> many1 space) >> nullParse) -sepAfter :: Parser a -> Parser a+sepAfter :: Monad m => ParserE m a -> ParserE m a sepAfter = between nullParse optionalSpace -sepAfter_ :: Parser a -> Parser ()+sepAfter_ :: Monad m => ParserE m a -> ParserE m () sepAfter_ = (>> return ()) . between nullParse optionalSpace -sepAfter1 :: Parser a -> Parser a+sepAfter1 :: Monad m => ParserE m a -> ParserE m a sepAfter1 = between nullParse requiredSpace -keyword :: String -> Parser ()+keyword :: Monad m => String -> ParserE m () keyword s = labeled s $ sepAfter $ string s >> (labeled "" $ notFollowedBy (many alphaNum)) -noKeywords :: Parser ()+noKeywords :: Monad m => ParserE m () noKeywords = notFollowedBy isKeyword -endOfDoc :: Parser ()+endOfDoc :: Monad m => ParserE m () endOfDoc = labeled "" $ optionalSpace >> eof -notAllowed :: Parser a -> String -> Parser ()+notAllowed :: ParserE m a -> String -> ParserE m () -- Based on implementation of notFollowedBy. notAllowed p s = (try p >> fail s) <|> return () -pragmaStart :: Parser ()+pragmaStart :: Monad m => ParserE m () pragmaStart = string_ "$" -pragmaEnd :: Parser ()+pragmaEnd :: Monad m => ParserE m () pragmaEnd = string_ "$" -pragmaArgsStart :: Parser ()+pragmaArgsStart :: Monad m => ParserE m () pragmaArgsStart = string_ "[" -pragmaArgsEnd :: Parser ()+pragmaArgsEnd :: Monad m => ParserE m () pragmaArgsEnd = string_ "]" -inferredParam :: Parser ()+inferredParam :: Monad m => ParserE m () inferredParam = string_ "?" -operator :: String -> Parser String+operator :: Monad m => String -> ParserE m String operator o = labeled o $ do   string_ o   notFollowedBy operatorSymbol   optionalSpace   return o -stringChar :: Parser Char+stringChar :: Monad m => ParserE m Char stringChar = escaped <|> notEscaped where   escaped = labeled "escaped char sequence" $ do     char_ '\\'@@ -433,6 +462,11 @@         return $ chr $ 16*h1 + h2   notEscaped = noneOf "\"" +quotedString :: Monad m => ParserE m String+quotedString = do+  string_ "\""+  manyTill stringChar (string_ "\"")+ digitVal :: Char -> Int digitVal c   | c >= '0' && c <= '9' = ord(c) - ord('0')@@ -440,27 +474,27 @@   | c >= 'a' && c <= 'f' = 10 + ord(c) - ord('a')   | otherwise = undefined -parseDec :: Parser Integer+parseDec :: Monad m => ParserE m Integer parseDec = fmap snd $ parseIntCommon 10 digit -parseHex :: Parser Integer+parseHex :: Monad m => ParserE m Integer parseHex = fmap snd $ parseIntCommon 16 hexDigit -parseOct :: Parser Integer+parseOct :: Monad m => ParserE m Integer parseOct = fmap snd $ parseIntCommon 8 octDigit -parseBin :: Parser Integer+parseBin :: Monad m => ParserE m Integer parseBin = fmap snd $ parseIntCommon 2 (oneOf "01") -parseSubOne :: Parser (Integer,Integer)+parseSubOne :: Monad m => ParserE m (Integer,Integer) parseSubOne = parseIntCommon 10 digit -parseIntCommon :: Integer -> Parser Char -> Parser (Integer,Integer)+parseIntCommon :: Monad m => Integer -> ParserE m Char -> ParserE m (Integer,Integer) parseIntCommon b p = do   ds <- many1 p   return $ foldl (\(n,x) y -> (n+1,b*x + (fromIntegral $ digitVal y :: Integer))) (0,0) ds -regexChar :: Parser String+regexChar :: Monad m => ParserE m String regexChar = escaped <|> notEscaped where   escaped = do     char_ '\\'@@ -492,3 +526,26 @@ merge3 :: (Foldable f, Monoid a, Monoid b, Monoid c) => f (a,b,c) -> (a,b,c) merge3 = foldr merge (mempty,mempty,mempty) where   merge (xs1,ys1,zs1) (xs2,ys2,zs2) = (xs1<>xs2,ys1<>ys2,zs1<>zs2)++parseAny2 :: Monad m => ParserE m a -> ParserE m b -> ParserE m ([a],[b])+parseAny2 p1 p2 = sepBy anyType optionalSpace >>= return . merge2 where+  anyType = p1' <|> p2'+  p1' = do+    x <- p1+    return ([x],[])+  p2' = do+    y <- p2+    return ([],[y])++parseAny3 :: Monad m => ParserE m a -> ParserE m b -> ParserE m c -> ParserE m ([a],[b],[c])+parseAny3 p1 p2 p3 = sepBy anyType optionalSpace >>= return . merge3 where+  anyType = p1' <|> p2' <|> p3'+  p1' = do+    x <- p1+    return ([x],[],[])+  p2' = do+    y <- p2+    return ([],[y],[])+  p3' = do+    z <- p3+    return ([],[],[z])
src/Parser/DefinedCategory.hs view
@@ -20,14 +20,13 @@ {-# LANGUAGE Safe #-}  module Parser.DefinedCategory (-  parseAnySource, ) where  import Control.Monad (when) import Prelude hiding (pi) import Text.Parsec-import Text.Parsec.String +import Base.CompileError import Parser.Common import Parser.Procedure () import Parser.TypeCategory@@ -89,40 +88,24 @@         t <- sourceParser         return (s,t) -parseMemberProcedureFunction ::-  CategoryName ->-  Parser ([DefinedMember SourcePos],[ExecutableProcedure SourcePos],[ScopedFunction SourcePos])-parseMemberProcedureFunction n = parsed >>= return . foldr merge empty where-  empty = ([],[],[])-  merge (ms1,ps1,fs1) (ms2,ps2,fs2) = (ms1++ms2,ps1++ps2,fs1++fs2)-  parsed = sepBy anyType optionalSpace-  anyType = labeled "" $ catchUnscopedType <|> singleMember <|> singleProcedure <|> singleFunction-  singleMember = labeled "member" $ do-    m <- sourceParser-    return ([m],[],[])-  singleProcedure = labeled "procedure" $ do-    p <- sourceParser-    return ([],[p],[])-  singleFunction = labeled "function" $ do-    f <- try $ parseScopedFunction parseScope (return n)-    p <- labeled ("definition of function " ++ show (sfName f)) $ sourceParser-    when (sfName f /= epName p) $-      fail $ "expecting definition of function " ++ show (sfName f) ++-             " but got definition of " ++ show (epName p)-    return ([],[p],[f])-  catchUnscopedType = do-    _ <- try sourceParser :: Parser ValueType-    fail $ "members must have an explicit @value or @category scope"--parseAnySource :: Parser ([AnyCategory SourcePos],[DefinedCategory SourcePos])-parseAnySource = parsed >>= return . foldr merge empty where-  empty = ([],[])-  merge (cs1,ds1) (cs2,ds2) = (cs1++cs2,ds1++ds2)-  parsed = sepBy anyType optionalSpace-  anyType = singleCategory <|> singleDefine2-  singleCategory = do-    c <- sourceParser-    return ([c],[])-  singleDefine2 = do-    d <- sourceParser-    return ([],[d])+parseMemberProcedureFunction :: CompileErrorM m =>+  CategoryName -> ParserE m ([DefinedMember SourcePos],+                             [ExecutableProcedure SourcePos],+                             [ScopedFunction SourcePos])+parseMemberProcedureFunction n = do+  (ms,ps,fs) <- parseAny3 (catchUnscopedType <|> sourceParser) sourceParser singleFunction+  let ps2 = ps ++ map snd fs+  let fs2 = map fst fs+  return (ms,ps2,fs2) where+    singleFunction = labeled "function" $ do+      f <- parseScopedFunction parseScope (return n)+      c <- getPosition+      p <- labeled ("definition of function " ++ show (sfName f)) $ sourceParser+      when (sfName f /= epName p) $+        parseErrorM c $ "expecting definition of function " ++ show (sfName f) +++                        " but got definition of " ++ show (epName p)+      return (f,p)+    catchUnscopedType = labeled "" $ do+      c <- getPosition+      _ <- try sourceParser :: CompileErrorM m => ParserE m ValueType+      parseErrorM c "members must have an explicit @value or @category scope"
src/Parser/IntegrationTest.hs view
@@ -25,7 +25,7 @@ import Text.Parsec  import Parser.Common-import Parser.DefinedCategory+import Parser.DefinedCategory () import Parser.Procedure () import Parser.TypeCategory () import Types.IntegrationTest@@ -39,9 +39,15 @@     name <- manyTill stringChar (string_ "\"")     optionalSpace     sepAfter (string_ "{")-    result <- resultError <|> resultCrash <|> resultSuccess+    result <- resultCompiles <|> resultError <|> resultCrash <|> resultSuccess+    args <- parseArgs <|> return []     sepAfter (string_ "}")-    return $ IntegrationTestHeader [c] name result where+    return $ IntegrationTestHeader [c] name args result where+      resultCompiles = labeled "compiles expectation" $ do+        c <- getPosition+        try $ sepAfter (keyword "compiles")+        (req,exc) <- requireOrExclude+        return $ ExpectCompiles [c] req exc       resultError = labeled "error expectation" $ do         c <- getPosition         sepAfter (keyword "error")@@ -49,16 +55,17 @@         return $ ExpectCompileError [c] req exc       resultCrash = labeled "crash expectation" $ do         c <- getPosition-        sepAfter (keyword "crash")-        e <- labeled "test expression" sourceParser+        try $ sepAfter (keyword "crash")         (req,exc) <- requireOrExclude-        return $ ExpectRuntimeError [c] e req exc+        return $ ExpectRuntimeError [c] req exc       resultSuccess = labeled "success expectation" $ do         c <- getPosition         sepAfter (keyword "success")-        e <- labeled "test expression" sourceParser         (req,exc) <- requireOrExclude-        return $ ExpectRuntimeSuccess [c] e req exc+        return $ ExpectRuntimeSuccess [c] req exc+      parseArgs = labeled "testcase args" $ do+        sepAfter (keyword "args")+        many (sepAfter quotedString)       requireOrExclude = parsed >>= return . foldr merge empty where         empty = ([],[])         merge (cs1,ds1) (cs2,ds2) = (cs1++cs2,ds1++ds2)@@ -91,5 +98,5 @@ instance ParseFromSource (IntegrationTest SourcePos) where   sourceParser = labeled "integration test" $ do     h <- sourceParser-    (cs,ds) <- parseAnySource-    return $ IntegrationTest h cs ds+    (cs,ds,ts) <- parseAny3 sourceParser sourceParser sourceParser+    return $ IntegrationTest h cs ds ts
src/Parser/Pragma.hs view
@@ -19,7 +19,6 @@ {-# LANGUAGE Safe #-}  module Parser.Pragma (-  parseMacroName,   parsePragmas,   pragmaComment,   pragmaExprLookup,@@ -32,49 +31,49 @@  import Control.Monad (when) import Text.Parsec-import Text.Parsec.String +import Base.CompileError import Parser.Common import Types.Pragma  -parsePragmas :: [Parser a] -> Parser [a]+parsePragmas :: CompileErrorM m => [ParserE m a] -> ParserE m [a] parsePragmas = many . foldr ((<|>)) unknownPragma -pragmaModuleOnly :: Parser (Pragma SourcePos)+pragmaModuleOnly :: CompileErrorM m => ParserE m (Pragma SourcePos) pragmaModuleOnly = autoPragma "ModuleOnly" $ Left parseAt where   parseAt c = PragmaVisibility [c] ModuleOnly -parseMacroName :: Parser String-parseMacroName = labeled "macro name" $ do-  h <- upper <|> char '_'-  t <- many (upper <|> digit <|> char '_')-  optionalSpace-  return (h:t)+instance ParseFromSource MacroName where+  sourceParser = labeled "macro name" $ do+    h <- upper <|> char '_'+    t <- many (upper <|> digit <|> char '_')+    optionalSpace+    return $ MacroName (h:t) -pragmaExprLookup :: Parser (Pragma SourcePos)+pragmaExprLookup :: CompileErrorM m => ParserE m (Pragma SourcePos) pragmaExprLookup = autoPragma "ExprLookup" $ Right parseAt where   parseAt c = do-    name <- parseMacroName+    name <- sourceParser     return $ PragmaExprLookup [c] name -pragmaSourceContext :: Parser (Pragma SourcePos)+pragmaSourceContext :: CompileErrorM m => ParserE m (Pragma SourcePos) pragmaSourceContext = autoPragma "SourceContext" $ Left parseAt where   parseAt c = PragmaSourceContext c -pragmaNoTrace :: Parser (Pragma SourcePos)+pragmaNoTrace :: CompileErrorM m => ParserE m (Pragma SourcePos) pragmaNoTrace = autoPragma "NoTrace" $ Left parseAt where   parseAt c = PragmaTracing [c] NoTrace -pragmaTraceCreation :: Parser (Pragma SourcePos)+pragmaTraceCreation :: CompileErrorM m => ParserE m (Pragma SourcePos) pragmaTraceCreation = autoPragma "TraceCreation" $ Left parseAt where   parseAt c = PragmaTracing [c] TraceCreation -pragmaTestsOnly :: Parser (Pragma SourcePos)+pragmaTestsOnly :: CompileErrorM m => ParserE m (Pragma SourcePos) pragmaTestsOnly = autoPragma "TestsOnly" $ Left parseAt where   parseAt c = PragmaVisibility [c] TestsOnly -pragmaComment :: Parser (Pragma SourcePos)+pragmaComment :: CompileErrorM m => ParserE m (Pragma SourcePos) pragmaComment = autoPragma "Comment" $ Right parseAt where   parseAt c = do     string_ "\""@@ -82,13 +81,14 @@     optionalSpace     return $ PragmaComment [c] ss -unknownPragma :: Parser a+unknownPragma :: CompileErrorM m => ParserE m a unknownPragma = do+  c <- getPosition   try pragmaStart   p <- many1 alphaNum-  fail $ "Pragma " ++ p ++ " is not supported in this context"+  parseErrorM c $ "pragma " ++ p ++ " is not supported in this context" -autoPragma :: String -> Either (SourcePos -> a) (SourcePos -> Parser a) -> Parser a+autoPragma :: CompileErrorM m => String -> Either (SourcePos -> a) (SourcePos -> ParserE m a) -> ParserE m a autoPragma p f = do   c <- getPosition   try $ pragmaStart >> string_ p >> notFollowedBy alphaNum@@ -97,11 +97,11 @@   if hasArgs      then do        extra <- manyTill anyChar (string_ "]$")-       when (not $ null extra) $ fail $ "Content unused by pragma " ++ p ++ ": " ++ extra+       when (not $ null extra) $ parseErrorM c $ "content unused by pragma " ++ p ++ ": " ++ extra        optionalSpace      else sepAfter pragmaEnd   return x where     delegate False (Left f2)  c = return $ f2 c     delegate True  (Right f2) c = f2 c-    delegate _     (Left _)   _ = fail $ "Pragma " ++ p ++ " does not allow arguments using []"-    delegate _     (Right _)  _ = fail $ "Pragma " ++ p ++ " requires arguments using []"+    delegate _     (Left _)   c = parseErrorM c $ "pragma " ++ p ++ " does not allow arguments using []"+    delegate _     (Right _)  c = parseErrorM c $ "pragma " ++ p ++ " requires arguments using []"
src/Parser/Procedure.hs view
@@ -23,10 +23,11 @@ module Parser.Procedure ( ) where +import Control.Applicative (empty) import Text.Parsec-import Text.Parsec.String import qualified Data.Set as Set +import Base.CompileError import Parser.Common import Parser.Pragma import Parser.TypeCategory ()@@ -50,6 +51,16 @@     sepAfter (string_ "}")     return $ ExecutableProcedure [c] pragmas [c2] n as rs pp +instance ParseFromSource (TestProcedure SourcePos) where+  sourceParser = labeled "test procedure" $ do+    c <- getPosition+    kwUnittest+    n <- try sourceParser+    sepAfter (string_ "{")+    pp <- sourceParser+    sepAfter (string_ "}")+    return $ TestProcedure [c] n pp+ instance ParseFromSource (ArgValues SourcePos) where   sourceParser = labeled "procedure arguments" $ do     c <- getPosition@@ -139,12 +150,12 @@       c <- getPosition       try kwReturn       emptyReturn c <|> multiReturn c-    multiReturn :: SourcePos -> Parser (Statement SourcePos)+    multiReturn :: CompileErrorM m => SourcePos -> ParserE m (Statement SourcePos)     multiReturn c = do       rs <- sepBy sourceParser (sepAfter $ string_ ",")       statementEnd       return $ ExplicitReturn [c] (Positional rs)-    emptyReturn :: SourcePos -> Parser (Statement SourcePos)+    emptyReturn :: CompileErrorM m => SourcePos -> ParserE m (Statement SourcePos)     emptyReturn c = do       kwIgnore       statementEnd@@ -167,8 +178,9 @@       strayFuncCall <|> return ()       return $ ExistingVariable n     strayFuncCall = do+      c <- getPosition       valueSymbolGet <|> typeSymbolGet <|> categorySymbolGet-      fail "function returns must be explicitly handled"+      parseErrorM c "function returns must be explicitly handled"  instance ParseFromSource (VoidExpression SourcePos) where   sourceParser = conditional <|> loop <|> scoped where@@ -240,9 +252,9 @@       p <- between (sepAfter $ string_ "{") (sepAfter $ string_ "}") sourceParser       return $ NoValueExpression [c] (Unconditional p) -unaryOperator :: Parser (Operator c)+unaryOperator :: Monad m => ParserE m (Operator c) unaryOperator = op >>= return . NamedOperator where-  op = labeled "unary operator" $ foldr (<|>) (fail "empty") $ map (try . operator) ops+  op = labeled "unary operator" $ foldr (<|>) empty $ map (try . operator) ops   ops = logicalUnary ++ arithUnary ++ bitwiseUnary  logicalUnary :: [String]@@ -254,9 +266,9 @@ bitwiseUnary :: [String] bitwiseUnary = ["~"] -infixOperator :: Parser (Operator c)+infixOperator :: Monad m => ParserE m (Operator c) infixOperator = op >>= return . NamedOperator where-  op = labeled "binary operator" $ foldr (<|>) (fail "empty") $ map (try . operator) ops+  op = labeled "binary operator" $ foldr (<|>) empty $ map (try . operator) ops   ops = compareInfix ++ logicalInfix ++ addInfix ++ subInfix ++ multInfix ++ bitwiseInfix ++ bitshiftInfix  compareInfix :: [String]@@ -290,7 +302,7 @@     | o `Set.member` Set.fromList logicalInfix = 5   infixOrder _ = 3 -functionOperator :: Parser (Operator SourcePos)+functionOperator :: CompileErrorM m => ParserE m (Operator SourcePos) functionOperator = do   c <- getPosition   infixFuncStart@@ -403,7 +415,7 @@       sepAfter_ inferredParam       return $ InferredInstance [c] -parseFunctionCall :: SourcePos -> FunctionName -> Parser (FunctionCall SourcePos)+parseFunctionCall :: CompileErrorM m => SourcePos -> FunctionName -> ParserE m (FunctionCall SourcePos) parseFunctionCall c n = do   -- NOTE: try is needed here so that < operators work when the left side is   -- just a variable name, e.g., x < y.@@ -415,8 +427,8 @@                 (sepBy sourceParser (sepAfter $ string_ ","))   return $ FunctionCall [c] n (Positional ps) (Positional es) -builtinFunction :: Parser FunctionName-builtinFunction = foldr (<|>) (fail "empty") $ map try [+builtinFunction :: Monad m => ParserE m FunctionName+builtinFunction = foldr (<|>) empty $ map try [     kwPresent >> return BuiltinPresent,     kwReduce >> return BuiltinReduce,     kwRequire >> return BuiltinRequire,@@ -440,13 +452,13 @@       e <- try (assign c) <|> expr c       sepAfter (string_ ")")       return e-    assign :: SourcePos -> Parser (ExpressionStart SourcePos)+    assign :: CompileErrorM m => SourcePos -> ParserE m (ExpressionStart SourcePos)     assign c = do       n <- sourceParser       assignOperator       e <- sourceParser       return $ InlineAssignment [c] n e-    expr :: SourcePos -> Parser (ExpressionStart SourcePos)+    expr :: CompileErrorM m => SourcePos -> ParserE m (ExpressionStart SourcePos)     expr c = do       e <- sourceParser       return $ ParensExpression [c] e@@ -471,7 +483,7 @@            _ -> undefined  -- Should be caught above.     variableOrUnqualified = do       c <- getPosition-      n <- sourceParser :: Parser VariableName+      n <- sourceParser :: CompileErrorM m => ParserE m VariableName       asUnqualifiedCall c n <|> asVariable c n     asVariable c n = do       return $ NamedVariable (OutputValue [c] n)@@ -505,8 +517,7 @@                  emptyLiteral where     stringLiteral = do       c <- getPosition-      string_ "\""-      ss <- manyTill stringChar (string_ "\"")+      ss <- quotedString       optionalSpace       return $ StringLiteral [c] ss     charLiteral = do
src/Parser/SourceFile.hs view
@@ -25,11 +25,10 @@ ) where  import Text.Parsec-import Text.Parsec.String  import Base.CompileError import Parser.Common-import Parser.DefinedCategory+import Parser.DefinedCategory () import Parser.IntegrationTest () import Parser.Pragma import Parser.TypeCategory ()@@ -41,21 +40,15 @@  parseInternalSource :: CompileErrorM m =>   (FilePath,String) -> m ([Pragma SourcePos],[AnyCategory SourcePos],[DefinedCategory SourcePos])-parseInternalSource (f,s) = unwrap parsed where-  parsed = parse (between optionalSpace endOfDoc withPragmas) f s-  unwrap (Left e)  = compileErrorM (show e)-  unwrap (Right t) = return t+parseInternalSource (f,s) = runParserE (between optionalSpace endOfDoc withPragmas) f s where   withPragmas = do     pragmas <- parsePragmas internalSourcePragmas     optionalSpace-    (cs,ds) <- parseAnySource+    (cs,ds) <- parseAny2 sourceParser sourceParser     return (pragmas,cs,ds)  parsePublicSource :: CompileErrorM m => (FilePath,String) -> m ([Pragma SourcePos],[AnyCategory SourcePos])-parsePublicSource (f,s) = unwrap parsed where-  parsed = parse (between optionalSpace endOfDoc withPragmas) f s-  unwrap (Left e)  = compileErrorM (show e)-  unwrap (Right t) = return t+parsePublicSource (f,s) = runParserE (between optionalSpace endOfDoc withPragmas) f s where   withPragmas = do     pragmas <- parsePragmas publicSourcePragmas     optionalSpace@@ -63,21 +56,18 @@     return (pragmas,cs)  parseTestSource :: CompileErrorM m => (FilePath,String) -> m ([Pragma SourcePos],[IntegrationTest SourcePos])-parseTestSource (f,s) = unwrap parsed where-  parsed = parse (between optionalSpace endOfDoc withPragmas) f s-  unwrap (Left e)  = compileErrorM (show e)-  unwrap (Right t) = return t+parseTestSource (f,s) = runParserE (between optionalSpace endOfDoc withPragmas) f s where   withPragmas = do     pragmas <- parsePragmas testSourcePragmas     optionalSpace     ts <- sepBy sourceParser optionalSpace     return (pragmas,ts) -publicSourcePragmas :: [Parser (Pragma SourcePos)]+publicSourcePragmas :: CompileErrorM m => [ParserE m (Pragma SourcePos)] publicSourcePragmas = [pragmaModuleOnly,pragmaTestsOnly] -internalSourcePragmas :: [Parser (Pragma SourcePos)]+internalSourcePragmas :: CompileErrorM m => [ParserE m (Pragma SourcePos)] internalSourcePragmas = [pragmaTestsOnly] -testSourcePragmas :: [Parser (Pragma SourcePos)]+testSourcePragmas :: CompileErrorM m => [ParserE m (Pragma SourcePos)] testSourcePragmas = []
src/Parser/TypeCategory.hs view
@@ -29,8 +29,8 @@ ) where  import Text.Parsec-import Text.Parsec.String +import Base.CompileError import Parser.Common import Parser.TypeInstance () import Types.Positional@@ -74,7 +74,7 @@       close       return $ ValueConcrete [c] NoNamespace n ps rs ds vs fs -parseCategoryParams :: Parser [ValueParam SourcePos]+parseCategoryParams :: CompileErrorM m => ParserE m [ValueParam SourcePos] parseCategoryParams = do   (con,inv,cov) <- none <|> try fixedOnly <|> try noFixed <|> try explicitFixed   return $ map (apply Contravariant) con ++@@ -114,41 +114,40 @@       return (c,n)     apply v (c,n) = ValueParam [c] n v -singleRefine :: Parser (ValueRefine SourcePos)+singleRefine :: CompileErrorM m => ParserE m (ValueRefine SourcePos) singleRefine = do   c <- getPosition   try kwRefines   t <- sourceParser   return $ ValueRefine [c] t -singleDefine :: Parser (ValueDefine SourcePos)+singleDefine :: CompileErrorM m => ParserE m (ValueDefine SourcePos) singleDefine = do   c <- getPosition   try kwDefines   t <- sourceParser   return $ ValueDefine [c] t -singleFilter :: Parser (ParamFilter SourcePos)+singleFilter :: CompileErrorM m => ParserE m (ParamFilter SourcePos) singleFilter = try $ do   c <- getPosition   n <- sourceParser   f <- sourceParser   return $ ParamFilter [c] n f -parseCategoryRefines :: Parser [ValueRefine SourcePos]+parseCategoryRefines :: CompileErrorM m => ParserE m [ValueRefine SourcePos] parseCategoryRefines = sepAfter $ sepBy singleRefine optionalSpace -parseFilters :: Parser [ParamFilter SourcePos]+parseFilters :: CompileErrorM m => ParserE m [ParamFilter SourcePos] parseFilters = sepBy singleFilter optionalSpace -parseRefinesFilters :: Parser ([ValueRefine SourcePos],[ParamFilter SourcePos])+parseRefinesFilters :: CompileErrorM m => ParserE m ([ValueRefine SourcePos],[ParamFilter SourcePos]) parseRefinesFilters = parsed >>= return . merge2 where   parsed = sepBy anyType optionalSpace   anyType = labeled "refine or param filter" $ put12 singleRefine <|> put22 singleFilter -parseRefinesDefinesFilters :: Parser ([ValueRefine SourcePos],-                                      [ValueDefine SourcePos],-                                      [ParamFilter SourcePos])+parseRefinesDefinesFilters :: CompileErrorM m =>+  ParserE m ([ValueRefine SourcePos],[ValueDefine SourcePos],[ParamFilter SourcePos]) parseRefinesDefinesFilters = parsed >>= return . merge3 where   parsed = sepBy anyType optionalSpace   anyType =@@ -161,13 +160,11 @@     e <- sepAfter $ many alphaNum     return $ FunctionName (b:e) -parseScopedFunction :: Parser SymbolScope -> Parser CategoryName ->-                       Parser (ScopedFunction SourcePos)+parseScopedFunction :: CompileErrorM m =>+  ParserE m SymbolScope -> ParserE m CategoryName -> ParserE m (ScopedFunction SourcePos) parseScopedFunction sp tp = labeled "function" $ do   c <- getPosition-  s <- try sp -- Could be a constant, i.e., nothing consumed.-  t <- try tp -- Same here.-  n <- try sourceParser+  (s,t,n) <- try parseName   ps <- fmap Positional $ noParams <|> someParams   fa <- parseFilters   as <- fmap Positional $ typeList "argument type"@@ -175,6 +172,11 @@   rs <- fmap Positional $ typeList "return type"   return $ ScopedFunction [c] n t s as rs ps fa []   where+    parseName = do+      s <- sp -- Could be a constant, i.e., nothing consumed.+      t <- tp -- Same here.+      n <- sourceParser+      return (s,t,n)     noParams = notFollowedBy (string "<") >> return []     someParams = between (sepAfter $ string_ "<")                          (sepAfter $ string_ ">")@@ -191,14 +193,14 @@       t <- sourceParser       return $ PassedValue [c] t -parseScope :: Parser SymbolScope+parseScope :: Monad m => ParserE m SymbolScope parseScope = try categoryScope <|> try typeScope <|> valueScope -categoryScope :: Parser SymbolScope+categoryScope :: Monad m => ParserE m SymbolScope categoryScope = kwCategory >> return CategoryScope -typeScope :: Parser SymbolScope+typeScope :: Monad m => ParserE m SymbolScope typeScope = kwType >> return TypeScope -valueScope :: Parser SymbolScope+valueScope :: Monad m => ParserE m SymbolScope valueScope = kwValue >> return ValueScope
src/Test/Common.hs view
@@ -46,7 +46,6 @@ import System.FilePath import System.IO import Text.Parsec-import Text.Parsec.String import qualified Data.Map as Map import qualified Data.Set as Set @@ -72,26 +71,16 @@   | otherwise        = Right (getCompileSuccess c)  forceParse :: ParseFromSource a => String -> a-forceParse s = force $ parse sourceParser "(string)" s where-  force (Right x) = x-  force _         = undefined+forceParse s = getCompileSuccess $ runParserE sourceParser "(string)" s  readSingle :: ParseFromSource a => String -> String -> CompileInfo a-readSingle = readSingleWith (optionalSpace >> sourceParser)+readSingle  = readSingleWith sourceParser -readSingleWith :: Parser a -> String -> String -> CompileInfo a-readSingleWith p f s =-  unwrap $ parse (between nullParse endOfDoc p) f s-  where-    unwrap (Left e)  = compileErrorM (show e)-    unwrap (Right t) = return t+readSingleWith :: ParserE CompileInfo a -> String -> String -> CompileInfo a+readSingleWith p = runParserE (between nullParse endOfDoc p)  readMulti :: ParseFromSource a => String -> String -> CompileInfo [a]-readMulti f s =-  unwrap $ parse (between optionalSpace endOfDoc (sepBy sourceParser optionalSpace)) f s-  where-    unwrap (Left e)  = compileErrorM (show e)-    unwrap (Right t) = return t+readMulti f s = runParserE (between optionalSpace endOfDoc (sepBy sourceParser optionalSpace)) f s  parseFilterMap :: [(String,[String])] -> CompileInfo ParamFilters parseFilterMap pa = do@@ -118,7 +107,7 @@   check $ validateGeneralInstance r pa2 t   where     prefix = x ++ " " ++ showParams pa-    check x2 = x2 <!! (prefix ++ ":")+    check x2 = x2 <!! prefix ++ ":"  checkTypeFail :: TypeResolver r => r -> [(String,[String])] -> String -> CompileInfo () checkTypeFail r pa x = do@@ -137,7 +126,7 @@   check $ validateDefinesInstance r pa2 t   where     prefix = x ++ " " ++ showParams pa-    check x2 = x2 <!! (prefix ++ ":")+    check x2 = x2 <!! prefix ++ ":"  checkDefinesFail :: TypeResolver r => r -> [(String,[String])] -> String -> CompileInfo () checkDefinesFail r pa x = do@@ -158,7 +147,7 @@  containsNoDuplicates :: (Ord a, Show a) => [a] -> CompileInfo () containsNoDuplicates expected =-  (mapErrorsM_ checkSingle $ group $ sort expected) <!! (show expected)+  (mapErrorsM_ checkSingle $ group $ sort expected) <!! show expected   where     checkSingle xa@(x:_:_) =       compileErrorM $ "Item " ++ show x ++ " occurs " ++ show (length xa) ++ " times"@@ -167,7 +156,7 @@ containsAtLeast :: (Ord a, Show a) => [a] -> [a] -> CompileInfo () containsAtLeast actual expected =   (mapErrorsM_ (checkInActual $ Set.fromList actual) expected) <!!-        (show actual ++ " (actual) vs. " ++ show expected ++ " (expected)")+        show actual ++ " (actual) vs. " ++ show expected ++ " (expected)"   where     checkInActual va v =       if v `Set.member` va@@ -177,7 +166,7 @@ containsAtMost :: (Ord a, Show a) => [a] -> [a] -> CompileInfo () containsAtMost actual expected =   (mapErrorsM_ (checkInExpected $ Set.fromList expected) actual) <!!-        (show actual ++ " (actual) vs. " ++ show expected ++ " (expected)")+        show actual ++ " (actual) vs. " ++ show expected ++ " (expected)"   where     checkInExpected va v =       if v `Set.member` va
src/Test/IntegrationTest.hs view
@@ -31,17 +31,32 @@ import Test.Common import Types.DefinedCategory import Types.IntegrationTest-import Types.Positional-import Types.Procedure import Types.TypeCategory-import Types.TypeInstance   tests :: [IO (CompileInfo ())] tests = [     checkFileContents+      ("testfiles" </> "basic_compiles_test.0rt")+      (\t -> do+        let h = itHeader t+        when (not $ isExpectCompiles $ ithResult h) $ compileErrorM "Expected ExpectCompiles"+        checkEquals (ithTestName h) "basic compiles test"+        containsExactly (getRequirePattern $ ithResult h) [+            OutputPattern OutputCompiler "pattern in output 1",+            OutputPattern OutputAny      "pattern in output 2"+          ]+        containsExactly (getExcludePattern $ ithResult h) [+            OutputPattern OutputStderr "pattern not in output 1",+            OutputPattern OutputStdout "pattern not in output 2"+          ]+        containsExactly (extractCategoryNames t) ["Test"]+        containsExactly (extractDefinitionNames t) ["Test"]+        ),++    checkFileContents       ("testfiles" </> "basic_error_test.0rt")-      (\t -> return $ do+      (\t -> do         let h = itHeader t         when (not $ isExpectCompileError $ ithResult h) $ compileErrorM "Expected ExpectCompileError"         checkEquals (ithTestName h) "basic error test"@@ -59,17 +74,10 @@      checkFileContents       ("testfiles" </> "basic_crash_test.0rt")-      (\t -> return $ do+      (\t -> do         let h = itHeader t         when (not $ isExpectRuntimeError $ ithResult h) $ compileErrorM "Expected ExpectRuntimeError"         checkEquals (ithTestName h) "basic crash test"-        let match = case ereExpression $ ithResult h of-                         (Expression _-                           (TypeCall _-                             (JustTypeInstance (TypeInstance (CategoryName "Test") (Positional [])))-                             (FunctionCall _ (FunctionName "execute") (Positional []) (Positional []))) []) -> True-                         _ -> False-        when (not match) $ compileErrorM "Expected test expression \"Test$execute()\""         containsExactly (getRequirePattern $ ithResult h) [             OutputPattern OutputAny "pattern in output 1",             OutputPattern OutputAny "pattern in output 2"@@ -84,17 +92,10 @@      checkFileContents       ("testfiles" </> "basic_success_test.0rt")-      (\t -> return $ do+      (\t -> do         let h = itHeader t         when (not $ isExpectRuntimeSuccess $ ithResult h) $ compileErrorM "Expected ExpectRuntimeSuccess"         checkEquals (ithTestName h) "basic success test"-        let match = case ersExpression $ ithResult h of-                         (Expression _-                           (TypeCall _-                             (JustTypeInstance (TypeInstance (CategoryName "Test") (Positional [])))-                             (FunctionCall _ (FunctionName "execute") (Positional []) (Positional []))) []) -> True-                         _ -> False-        when (not match) $ compileErrorM "Expected test expression \"Test$execute()\""         containsExactly (getRequirePattern $ ithResult h) [             OutputPattern OutputAny "pattern in output 1",             OutputPattern OutputAny "pattern in output 2"@@ -109,13 +110,11 @@   ]  checkFileContents ::-  String -> (IntegrationTest SourcePos -> IO (CompileInfo ())) -> IO (CompileInfo ())-checkFileContents f o = do-  s <- loadFile f-  unwrap $ parse (between optionalSpace endOfDoc sourceParser) f s-  where-    unwrap (Left e)  = return $ compileErrorM (show e)-    unwrap (Right t) = fmap (("Check " ++ f ++ ":") ??>) $ o t+  String -> (IntegrationTest SourcePos -> CompileInfo ()) -> IO (CompileInfo ())+checkFileContents f o = toCompileInfo $ do+  s <- errorFromIO $ loadFile f+  t <- runParserE (between optionalSpace endOfDoc sourceParser) f s+  fromCompileInfo $ o t <!! "Check " ++ f ++ ":"  extractCategoryNames :: IntegrationTest c -> [String] extractCategoryNames = map (show . getCategoryName) . itCategory
src/Test/ParseMetadata.hs view
@@ -30,94 +30,140 @@ import System.FilePath import Test.Common import Types.Positional+import Types.Pragma import Types.Procedure import Types.TypeCategory (FunctionName(..),Namespace(..)) import Types.TypeInstance (CategoryName(..)) -tests :: [IO (CompileInfo ())]-tests = [-    checkWriteThenRead $ CompileMetadata {-      cmVersionHash = VersionHash "0123456789ABCDEFabcdef",-      cmPath = "/home/project/special",-      cmPublicNamespace = StaticNamespace "public_ABCDEF",-      cmPrivateNamespace = StaticNamespace "private_ABCDEF",-      cmPublicDeps = [-        "/home/project/public-dep1",-        "/home/project/public-dep2"-      ],-      cmPrivateDeps = [-        "/home/project/private-dep1",-        "/home/project/private-dep2"-      ],-      cmPublicCategories = [-        CategoryName "MyCategory",-        CategoryName "MyOtherCategory"-      ],-      cmPrivateCategories = [-        CategoryName "PrivateCategory",-        CategoryName "PrivateOtherCategory"-      ],-      cmPublicSubdirs = [-        "/home/project/special/subdir1",-        "/home/project/special/subdir2"-      ],-      cmPrivateSubdirs = [-        "/home/project/special/subdir1",-        "/home/project/special/subdir2"-      ],-      cmPublicFiles = [-        "/home/project/special/category1.0rp",-        "/home/project/special/category2.0rp"-      ],-      cmPrivateFiles = [-        "/home/project/special/category1.0rx",-        "/home/project/special/category2.0rx"-      ],-      cmTestFiles = [-        "/home/project/special/category1.0rt",-        "/home/project/special/category2.0rt"-      ],-      cmHxxFiles = [-        "/home/project/special/category1.hpp",-        "/home/project/special/category2.hpp"-      ],-      cmCxxFiles = [-        "/home/project/special/category1.cpp",-        "/home/project/special/category2.cpp"-      ],-      cmBinaries = [-        "/home/project/special/binary1",-        "/home/project/special/binary2"-      ],-      cmLinkFlags = [++hugeCompileMetadata :: CompileMetadata  -- testfiles/module-cache.txt+hugeCompileMetadata = CompileMetadata {+    cmVersionHash = VersionHash "0123456789ABCDEFabcdef",+    cmPath = "/home/project/special",+    cmPublicNamespace = StaticNamespace "public_ABCDEF",+    cmPrivateNamespace = StaticNamespace "private_ABCDEF",+    cmPublicDeps = [+      "/home/project/public-dep1",+      "/home/project/public-dep2"+    ],+    cmPrivateDeps = [+      "/home/project/private-dep1",+      "/home/project/private-dep2"+    ],+    cmPublicCategories = [+      CategoryName "MyCategory",+      CategoryName "MyOtherCategory"+    ],+    cmPrivateCategories = [+      CategoryName "PrivateCategory",+      CategoryName "PrivateOtherCategory"+    ],+    cmPublicSubdirs = [+      "/home/project/special/subdir1",+      "/home/project/special/subdir2"+    ],+    cmPrivateSubdirs = [+      "/home/project/special/subdir1",+      "/home/project/special/subdir2"+    ],+    cmPublicFiles = [+      "/home/project/special/category1.0rp",+      "/home/project/special/category2.0rp"+    ],+    cmPrivateFiles = [+      "/home/project/special/category1.0rx",+      "/home/project/special/category2.0rx"+    ],+    cmTestFiles = [+      "/home/project/special/category1.0rt",+      "/home/project/special/category2.0rt"+    ],+    cmHxxFiles = [+      "/home/project/special/category1.hpp",+      "/home/project/special/category2.hpp"+    ],+    cmCxxFiles = [+      "/home/project/special/category1.cpp",+      "/home/project/special/category2.cpp"+    ],+    cmBinaries = [+      "/home/project/special/binary1",+      "/home/project/special/binary2"+    ],+    cmLinkFlags = [+      "-lm",+      "-ldl"+    ],+    cmObjectFiles = [+      CategoryObjectFile {+        cofCategory = CategoryIdentifier {+          ciPath = "/home/project/special",+          ciCategory = CategoryName "SpecialCategory",+          ciNamespace = StaticNamespace "public_ABCDEF"+        },+        cofRequires = [+          CategoryIdentifier {+            ciPath = "/home/project/private-dep1",+            ciCategory = CategoryName "PrivateCategory",+            ciNamespace = NoNamespace+          },+          UnresolvedCategory {+            ucCategory = CategoryName "UnresolvedCategory"+          }+        ],+        cofFiles = [+          "/home/project/special/object1.o",+          "/home/project/special/object1.o"+        ]+      }+    ]+  }++hugeModuleConfig :: ModuleConfig  -- testfiles/module-config.txt+hugeModuleConfig = ModuleConfig {+    mcRoot = "/home/projects",+    mcPath = "special",+    mcExprMap = [],+    mcPublicDeps = [+      "/home/project/public-dep1",+      "/home/project/public-dep2"+    ],+    mcPrivateDeps = [+      "/home/project/private-dep1",+      "/home/project/private-dep2"+    ],+    mcExtraFiles = [+      CategorySource {+        csSource = "extra1.cpp",+        csCategories = [+          CategoryName "Category1",+          CategoryName "Category2"+        ],+        csRequires = [+          CategoryName "DepCategory1",+          CategoryName "DepCategory2"+        ]+      },+      OtherSource {+        osSource = "extra2.cpp"+      }+    ],+    mcExtraPaths = [+      "extra1",+      "extra2"+    ],+    mcMode = CompileIncremental {+      ciLinkFlags = [         "-lm",         "-ldl"-      ],-      cmObjectFiles = [-        CategoryObjectFile {-          cofCategory = CategoryIdentifier {-            ciPath = "/home/project/special",-            ciCategory = CategoryName "SpecialCategory",-            ciNamespace = StaticNamespace "public_ABCDEF"-          },-          cofRequires = [-            CategoryIdentifier {-              ciPath = "/home/project/private-dep1",-              ciCategory = CategoryName "PrivateCategory",-              ciNamespace = NoNamespace-            },-            UnresolvedCategory {-              ucCategory = CategoryName "UnresolvedCategory"-            }-          ],-          cofFiles = [-            "/home/project/special/object1.o",-            "/home/project/special/object1.o"-          ]-        }       ]-    },+    }+  } +tests :: [IO (CompileInfo ())]+tests = [+    checkWriteThenRead hugeCompileMetadata,+     checkWriteFail "bad hash" $ CompileMetadata {       cmVersionHash = VersionHash "bad hash",       cmPath = "/home/project/special",@@ -227,50 +273,12 @@       cmObjectFiles = []     }, -    checkWriteThenRead $ ModuleConfig {-      mcRoot = "/home/projects",-      mcPath = "special",-      mcExprMap = [],-      mcPublicDeps = [-        "/home/project/public-dep1",-        "/home/project/public-dep2"-      ],-      mcPrivateDeps = [-        "/home/project/private-dep1",-        "/home/project/private-dep2"-      ],-      mcExtraFiles = [-        CategorySource {-          csSource = "extra1.cpp",-          csCategories = [-            CategoryName "Category1",-            CategoryName "Category2"-          ],-          csRequires = [-            CategoryName "DepCategory1",-            CategoryName "DepCategory2"-          ]-        },-        OtherSource {-          osSource = "extra2.cpp"-        }-      ],-      mcExtraPaths = [-        "extra1",-        "extra2"-      ],-      mcMode = CompileIncremental {-        ciLinkFlags = [-          "-lm",-          "-ldl"-        ]-      }-    },+    checkWriteThenRead hugeModuleConfig,      checkWriteFail "empty.+map" $ ModuleConfig {       mcRoot = "/home/projects",       mcPath = "special",-      mcExprMap = [("MACRO",Literal (StringLiteral [] "something"))],+      mcExprMap = [(MacroName "MACRO",Literal (StringLiteral [] "something"))],       mcPublicDeps = [],       mcPrivateDeps = [],       mcExtraFiles = [],@@ -351,25 +359,29 @@     checkWriteFail "compile mode" $ CompileRecompileRecursive,     checkWriteFail "compile mode" $ CreateTemplates, -    checkParsesAs ("testfiles" </> "module-config.txt")+    checkParsesAs ("testfiles" </> "macro-config.txt")       (\m -> case mcExprMap m of-                  [("MY_MACRO",+                  [(MacroName "MY_MACRO",                     Expression _ (BuiltinCall _                       (FunctionCall _ BuiltinRequire (Positional [])                         (Positional [Literal (EmptyLiteral _)]))) []),-                   ("MY_OTHER_MACRO",+                   (MacroName "MY_OTHER_MACRO",                     Expression _                       (TypeCall _ _                         (FunctionCall _ (FunctionName "execute") (Positional [])                           (Positional [Literal (StringLiteral _ "this is a string\n")]))) [])                     ] -> True-                  _ -> False)+                  _ -> False),++    checkParsesAs ("testfiles" </> "module-config.txt") (== hugeModuleConfig),++    checkParsesAs ("testfiles" </> "module-cache.txt") (== hugeCompileMetadata)   ]  checkWriteThenRead :: (Eq a, Show a, ConfigFormat a) => a -> IO (CompileInfo ()) checkWriteThenRead m = return $ do   text <- fmap spamComments $ autoWriteConfig m-  m' <- autoReadConfig "(string)" text <!! ("Serialized >>>\n\n" ++ text ++ "\n<<< Serialized\n\n")+  m' <- autoReadConfig "(string)" text <!! "Serialized >>>\n\n" ++ text ++ "\n<<< Serialized\n\n"   when (m' /= m) $     compileErrorM $ "Failed to match after write/read\n" ++                    "Before:\n" ++ show m ++ "\n" ++@@ -397,7 +409,7 @@   return $ check parsed contents   where     check x contents = do-      x' <- x <!! ("While parsing " ++ f)+      x' <- x <!! "While parsing " ++ f       when (not $ m x') $         compileErrorM $ "Failed to match after write/read\n" ++                        "Unparsed:\n" ++ contents ++ "\n" ++
src/Test/Parser.hs view
@@ -26,7 +26,6 @@ import Base.CompileInfo import Parser.Common import Test.Common-import Text.Parsec.String   tests :: [IO (CompileInfo ())]@@ -57,7 +56,7 @@     checkParseFail regexChar "\""   ] -checkParsesAs :: (Eq a, Show a) => Parser a -> [Char] -> a -> IO (CompileInfo ())+checkParsesAs :: (Eq a, Show a) => ParserE CompileInfo a -> [Char] -> a -> IO (CompileInfo ()) checkParsesAs p s m = return $ do   let parsed = readSingleWith p "(string)" s   check parsed@@ -69,7 +68,7 @@       | isCompileError c = compileErrorM $ "Parse '" ++ s ++ "':\n" ++ show (getCompileError c)       | otherwise = return () -checkParseFail :: Show a => Parser a -> [Char] -> IO (CompileInfo ())+checkParseFail :: Show a => ParserE CompileInfo a -> [Char] -> IO (CompileInfo ()) checkParseFail p s = do   let parsed = readSingleWith p "(string)" s   return $ check parsed
src/Test/Pragma.hs view
@@ -20,11 +20,11 @@  import Control.Monad (when) import Text.Parsec-import Text.Parsec.String import Text.Regex.TDFA -- Not safe!  import Base.CompileError import Base.CompileInfo+import Parser.Common import Parser.Pragma import Test.Common import Types.Pragma@@ -64,7 +64,7 @@      checkParsesAs "$ExprLookup[ \nMODULE_PATH /*comment*/\n ]$" (fmap (:[]) pragmaExprLookup)       (\e -> case e of-                  [PragmaExprLookup _ "MODULE_PATH"] -> True+                  [PragmaExprLookup _ (MacroName "MODULE_PATH")] -> True                   _ -> False),      checkParsesAs "/*only comments*/" (parsePragmas [pragmaModuleOnly,pragmaTestsOnly])@@ -98,7 +98,7 @@     checkParseError "$ExprLookup[ \"bad stuff\" ]$" "macro name" pragmaExprLookup   ] -checkParsesAs :: String -> Parser [Pragma SourcePos] -> ([Pragma SourcePos] -> Bool) -> IO (CompileInfo ())+checkParsesAs :: String -> ParserE CompileInfo [Pragma SourcePos] -> ([Pragma SourcePos] -> Bool) -> IO (CompileInfo ()) checkParsesAs s p m = return $ do   let parsed = readSingleWith p "(string)" s   check parsed@@ -110,7 +110,7 @@       | isCompileError c = compileErrorM $ "Parse '" ++ s ++ "':\n" ++ show (getCompileError c)       | otherwise = return () -checkParseError :: String -> String -> Parser (Pragma SourcePos) -> IO (CompileInfo ())+checkParseError :: String -> String -> ParserE CompileInfo (Pragma SourcePos) -> IO (CompileInfo ()) checkParseError s m p = return $ do   let parsed = readSingleWith p "(string)" s   check parsed
src/Test/Procedure.hs view
@@ -200,15 +200,15 @@     checkShortParseSuccess "x <- 123.0 + z.call()",     checkShortParseFail "x <- \"123\".call()",     checkShortParseFail "x <- 123.call()",-    checkShortParseSuccess " x <- 'x'",-    checkShortParseSuccess " x <- '\\xAA'",-    checkShortParseFail " x <- '\\xAAZ'",-    checkShortParseSuccess " x <- '\076'",-    checkShortParseFail " x <- '\\07'",-    checkShortParseSuccess " x <- '\\n'",-    checkShortParseFail " x <- 'x",-    checkShortParseFail " x <- 'xx'",-    checkShortParseSuccess " x <- \"'xx\"",+    checkShortParseSuccess "x <- 'x'",+    checkShortParseSuccess "x <- '\\xAA'",+    checkShortParseFail "x <- '\\xAAZ'",+    checkShortParseSuccess "x <- '\076'",+    checkShortParseFail "x <- '\\07'",+    checkShortParseSuccess "x <- '\\n'",+    checkShortParseFail "x <- 'x",+    checkShortParseFail "x <- 'xx'",+    checkShortParseSuccess "x <- \"'xx\"",      checkParsesAs "'\"'"                   (\e -> case e of
src/Test/TypeCategory.hs view
@@ -1194,7 +1194,7 @@     compileErrorM $ "Different item counts: " ++ show actual ++ " (actual) vs. " ++                    show expected ++ " (expected)"   | otherwise = mapErrorsM_ check (zip3 actual expected ([1..] :: [Int])) where-    check (a,e,n) = f a e <!! ("Item " ++ show n ++ " mismatch")+    check (a,e,n) = f a e <!! "Item " ++ show n ++ " mismatch"  containsPaired :: (Eq a, Show a) => [a] -> [a] -> CompileInfo () containsPaired = checkPaired checkSingle where@@ -1208,7 +1208,7 @@   let parsed = readMulti f contents :: CompileInfo [AnyCategory SourcePos]   return $ check (parsed >>= o >> return ())   where-    check x = x <!! ("Check " ++ f ++ ":")+    check x = x <!! "Check " ++ f ++ ":"  checkOperationFail :: String -> ([AnyCategory SourcePos] -> CompileInfo a) -> IO (CompileInfo ()) checkOperationFail f o = do
src/Test/TypeInstance.hs view
@@ -957,8 +957,8 @@   Map.Map CategoryName (Map.Map CategoryName (InstanceParams -> InstanceParams))   -> TypeInstance -> CategoryName -> m InstanceParams getParams ma (TypeInstance n1 ps1) n2 = do-  ra <- mapLookup ma n1 <?? ("In lookup of category " ++ show n1)-  f <- mapLookup ra n2 <?? ("In lookup of parent " ++ show n2 ++ " of " ++ show n1)+  ra <- mapLookup ma n1 <?? "In lookup of category " ++ show n1+  f <- mapLookup ra n2 <?? "In lookup of parent " ++ show n2 ++ " of " ++ show n1   return $ f ps1  getTypeFilters :: CompileErrorM m => TypeInstance -> m InstanceFilters
+ src/Test/testfiles/basic_compiles_test.0rt view
@@ -0,0 +1,19 @@+testcase "basic compiles test" {+  compiles+  require compiler "pattern in output 1"+  exclude stderr   "pattern not in output 1"+  require any      "pattern in output 2"+  exclude stdout   "pattern not in output 2"+}++concrete Test {+  @type execute () -> ()+}++define Test {+  execute () { }+}++unittest test {+  \ Test.execute()+}
src/Test/testfiles/basic_crash_test.0rt view
@@ -1,5 +1,5 @@ testcase "basic crash test" {-  crash Test.execute()+  crash   require "pattern in output 1"   exclude "pattern not in output 1"   require "pattern in output 2"@@ -12,4 +12,8 @@  define Test {   execute () { }+}++unittest test {+  \ Test.execute() }
src/Test/testfiles/basic_error_test.0rt view
@@ -13,3 +13,7 @@ define Test {   execute () { } }++unittest test {+  \ Test.execute()+}
src/Test/testfiles/basic_success_test.0rt view
@@ -1,5 +1,5 @@ testcase "basic success test" {-  success Test.execute()+  success   require "pattern in output 1"   exclude "pattern not in output 1"   require "pattern in output 2"@@ -12,4 +12,8 @@  define Test {   execute () { }+}++unittest test {+  \ Test.execute() }
src/Test/testfiles/concrete.0rx view
@@ -1,4 +1,3 @@-// A concrete type with contrived comments. concrete/*!!!*/Type<#a,#b // <- contravariant params              |#c,#d // <- invariant params              |#e,#f /* <- covariant params*/> {
+ src/Test/testfiles/macro-config.txt view
@@ -0,0 +1,12 @@+path: "testfiles"+expression_map: [+  expression_macro {+    name: MY_MACRO+    expression: require(empty)+  }+  expression_macro {+    name: MY_OTHER_MACRO+    expression: Type<Int>.execute("this is a string\012")+  }+]+mode: incremental {}
+ src/Test/testfiles/module-cache.txt view
@@ -0,0 +1,76 @@+public_categories: [+  MyCategory+  MyOtherCategory+]+private_categories: [+  PrivateCategory+  PrivateOtherCategory+]+public_subdirs: [+  "/home/project/special/subdir1"+  "/home/project/special/subdir2"+]+private_subdirs: [+  "/home/project/special/subdir1"+  "/home/project/special/subdir2"+]+version_hash: 0123456789ABCDEFabcdef+path: "/home/project/special"+public_namespace: public_ABCDEF+hxx_files: [+  "/home/project/special/category1.hpp"+  "/home/project/special/category2.hpp"+]+private_namespace: private_ABCDEF+public_deps: [+  "/home/project/public-dep1"+  "/home/project/public-dep2"+]+private_deps: [+  "/home/project/private-dep1"+  "/home/project/private-dep2"+]+private_files: [+  "/home/project/special/category1.0rx"+  "/home/project/special/category2.0rx"+]+test_files: [+  "/home/project/special/category1.0rt"+  "/home/project/special/category2.0rt"+]+public_files: [+  "/home/project/special/category1.0rp"+  "/home/project/special/category2.0rp"+]+cxx_files: [+  "/home/project/special/category1.cpp"+  "/home/project/special/category2.cpp"+]+object_files: [+  category_object {+    category: category {+      path: "/home/project/special"+      namespace: public_ABCDEF+      name: SpecialCategory+    }+    requires: [+      category {+        path: "/home/project/private-dep1"+        name: PrivateCategory+      }+      unresolved { name: UnresolvedCategory }+    ]+    files: [+      "/home/project/special/object1.o"+      "/home/project/special/object1.o"+    ]+  }+]+binaries: [+  "/home/project/special/binary1"+  "/home/project/special/binary2"+]+link_flags: [+  "-lm"+  "-ldl"+]
src/Test/testfiles/module-config.txt view
@@ -1,12 +1,36 @@-path: "testfiles"+public_deps: [+  "/home/project/public-dep1"+  "/home/project/public-dep2"+]+root: "/home/projects" expression_map: [-  expression_macro {-    name: MY_MACRO-    expression: require(empty)-  }-  expression_macro {-    name: MY_OTHER_MACRO-    expression: Type<Int>.execute("this is a string\012")+]+mode: incremental {+  link_flags: [+    "-lm"+    "-ldl"+  ]+}+private_deps: [+  "/home/project/private-dep1"+  "/home/project/private-dep2"+]+include_paths: [+  "extra1"+  "extra2"+]+path: "special"+extra_files: [+  category_source {+    requires: [+      DepCategory1+      DepCategory2+    ]+    source: "extra1.cpp"+    categories: [+      Category1+      Category2+    ]   }+  "extra2.cpp" ]-mode: incremental {}
src/Test/testfiles/test.0rt view
@@ -1,5 +1,9 @@ testcase "test" {-  success Test.run()+  success+}++unittest test {+  \ Test.run() }  concrete Test {
src/Types/IntegrationTest.hs view
@@ -27,19 +27,21 @@   getExcludePattern,   getRequirePattern,   isExpectCompileError,+  isExpectCompiles,   isExpectRuntimeError,   isExpectRuntimeSuccess, ) where  import Types.TypeCategory import Types.DefinedCategory-import Types.Procedure (Expression)+import Types.Procedure   data IntegrationTestHeader c =   IntegrationTestHeader {     ithContext :: [c],     ithTestName :: String,+    ithArgs :: [String],     ithResult :: ExpectedResult c   } @@ -47,7 +49,8 @@   IntegrationTest {     itHeader :: IntegrationTestHeader c,     itCategory :: [AnyCategory c],-    itDefinition :: [DefinedCategory c]+    itDefinition :: [DefinedCategory c],+    itTests :: [TestProcedure c]   }  data ExpectedResult c =@@ -56,15 +59,18 @@     eceRequirePattern :: [OutputPattern],     eceExcludePattern :: [OutputPattern]   } |+  ExpectCompiles {+    eceContext :: [c],+    eceRequirePattern :: [OutputPattern],+    eceExcludePattern :: [OutputPattern]+  } |   ExpectRuntimeError {     ereContext :: [c],-    ereExpression :: Expression c,     ereRequirePattern :: [OutputPattern],     ereExcludePattern :: [OutputPattern]   } |   ExpectRuntimeSuccess {     ersContext :: [c],-    ersExpression :: Expression c,     ersRequirePattern :: [OutputPattern],     ersExcludePattern :: [OutputPattern]   }@@ -78,24 +84,30 @@  data OutputScope = OutputAny | OutputCompiler | OutputStderr | OutputStdout deriving (Eq,Ord,Show) +isExpectCompiles :: ExpectedResult c -> Bool+isExpectCompiles (ExpectCompiles _ _ _) = True+isExpectCompiles _                      = False+ isExpectCompileError :: ExpectedResult c -> Bool isExpectCompileError (ExpectCompileError _ _ _) = True isExpectCompileError _                          = False  isExpectRuntimeError :: ExpectedResult c -> Bool-isExpectRuntimeError (ExpectRuntimeError _ _ _ _) = True-isExpectRuntimeError _                            = False+isExpectRuntimeError (ExpectRuntimeError _ _ _) = True+isExpectRuntimeError _                          = False  isExpectRuntimeSuccess :: ExpectedResult c -> Bool-isExpectRuntimeSuccess (ExpectRuntimeSuccess _ _ _ _) = True-isExpectRuntimeSuccess _                              = False+isExpectRuntimeSuccess (ExpectRuntimeSuccess _ _ _) = True+isExpectRuntimeSuccess _                            = False  getRequirePattern :: ExpectedResult c -> [OutputPattern]-getRequirePattern (ExpectCompileError _ rs _)     = rs-getRequirePattern (ExpectRuntimeError _ _ rs _)   = rs-getRequirePattern (ExpectRuntimeSuccess _ _ rs _) = rs+getRequirePattern (ExpectCompiles _ rs _)       = rs+getRequirePattern (ExpectCompileError _ rs _)   = rs+getRequirePattern (ExpectRuntimeError _ rs _)   = rs+getRequirePattern (ExpectRuntimeSuccess _ rs _) = rs  getExcludePattern :: ExpectedResult c -> [OutputPattern]-getExcludePattern (ExpectCompileError _ _ es)     = es-getExcludePattern (ExpectRuntimeError _ _ _ es)   = es-getExcludePattern (ExpectRuntimeSuccess _ _ _ es) = es+getExcludePattern (ExpectCompiles _ _ es)       = es+getExcludePattern (ExpectCompileError _ _ es)   = es+getExcludePattern (ExpectRuntimeError _ _ es)   = es+getExcludePattern (ExpectRuntimeSuccess _ _ es) = es
src/Types/Pragma.hs view
@@ -20,6 +20,7 @@  module Types.Pragma (   CodeVisibility(..),+  MacroName(..),   Pragma(..),   TraceType(..),   WithVisibility(..),@@ -59,6 +60,15 @@  data TraceType = NoTrace | TraceCreation deriving (Show) +newtype MacroName =+  MacroName {+    mnName :: String+  }+  deriving (Eq,Ord)++instance Show MacroName where+  show = mnName+ data Pragma c =   PragmaVisibility {     pvContext :: [c],@@ -66,7 +76,7 @@   } |   PragmaExprLookup {     pelContext :: [c],-    pelName :: String+    pelName :: MacroName   } |   PragmaSourceContext {     pscContext :: c
src/Types/Procedure.hs view
@@ -36,6 +36,7 @@   ReturnValues(..),   ScopedBlock(..),   Statement(..),+  TestProcedure(..),   ValueLiteral(..),   ValueOperation(..),   VariableName(..),@@ -139,6 +140,13 @@ instance Show c => Show (OutputValue c) where   show (OutputValue c v) = show v ++ " /*" ++ formatFullContext c ++ "*/" +data TestProcedure c =+  TestProcedure {+    tpContext :: [c],+    tpName :: FunctionName,+    tpProcedure :: Procedure c+  }+  deriving (Show)  data Procedure c =   Procedure [c] [Statement c]@@ -240,7 +248,7 @@  data ExpressionStart c =   NamedVariable (OutputValue c) |-  NamedMacro [c] String |+  NamedMacro [c] MacroName |   CategoryCall [c] CategoryName (FunctionCall c) |   TypeCall [c] TypeInstanceOrParam (FunctionCall c) |   UnqualifiedCall [c] (FunctionCall c) |
src/Types/TypeCategory.hs view
@@ -501,20 +501,16 @@ disallowBoundedParams :: CompileErrorM m => ParamFilters -> m () disallowBoundedParams = mapErrorsM_ checkBounds . Map.toList where   checkBounds (p,fs) = do-    let bs = splitBounds fs-    case bs of-         ([],_) -> return ()-         (_,[]) -> return ()-         (ls,hs) -> ("Param " ++ show p ++ " cannot have both lower and upper bounds") !!>-           collectAllM_ [-               mapErrorsM_ (filterAsError p) ls <!! "Lower bound:",-               mapErrorsM_ (filterAsError p) hs <!! "Upper bound:"-             ]-  splitBounds (f@(TypeFilter FilterRequires _):fs) = let (ls,hs) = splitBounds fs in (ls,f:hs)-  splitBounds (f@(TypeFilter FilterAllows   _):fs) = let (ls,hs) = splitBounds fs in (f:ls,hs)-  splitBounds (_:fs) = splitBounds fs-  splitBounds _ = ([],[])-  filterAsError p f = compileErrorM $ show p ++ " " ++ show f+    let (lb,ub) = foldr splitBounds (minBound,maxBound) fs+    when (lb /= minBound && ub /= maxBound) $+      ("Param " ++ show p ++ " cannot have both lower and upper bounds") !!>+        collectAllM_ [+            compileErrorM $ "Lower bound: " ++ show lb,+            compileErrorM $ "Upper bound: " ++ show ub+          ]+  splitBounds (TypeFilter FilterRequires t) (lb,ub) = (lb,t<&&>ub)+  splitBounds (TypeFilter FilterAllows   t) (lb,ub) = (t<||>lb,ub)+  splitBounds _ bs = bs  checkConnectedTypes :: (Show c, CompileErrorM m) =>   CategoryMap c -> [AnyCategory c] -> m ()@@ -1044,8 +1040,12 @@   }   deriving (Eq,Ord) -instance Show a => Show (GuessRange a) where-  show (GuessRange lo hi) = "Something between " ++ show lo ++ " and " ++ show hi+instance (Bounded a, Eq a, Show a) => Show (GuessRange a) where+  show (GuessRange lo hi)+    | lo == minBound && hi == maxBound = "Literally anything is possible"+    | lo == minBound = "Something at or below " ++ show hi+    | hi == maxBound = "Something at or above " ++ show lo+    | otherwise = "Something between " ++ show lo ++ " and " ++ show hi  data GuessUnion a =   GuessUnion {
src/Types/TypeInstance.hs view
@@ -355,7 +355,9 @@ checkGeneralMatch :: (CompileErrorM m, TypeResolver r) =>   r -> ParamFilters -> Variance ->   GeneralInstance -> GeneralInstance -> m (MergeTree InferredTypeGuess)-checkGeneralMatch r f v t1 t2 = collectFirstM [matchInferredRight,bothSingle,matchNormal v] where+checkGeneralMatch r f v t1 t2 = do+  ss <- collectFirstM [fmap Just bothSingle,return Nothing]+  collectFirstM [matchInferredRight,getMatcher ss] where   matchNormal Invariant =     mergeAllM [matchNormal Contravariant,matchNormal Covariant]   matchNormal Contravariant =@@ -368,7 +370,11 @@   bothSingle = do     t1' <- matchOnlyLeaf t1     t2' <- matchOnlyLeaf t2-    checkSingleMatch r f v t1' t2'+    return (t1',t2')+  getMatcher ss =+    case ss of+         Just (t1',t2') -> checkSingleMatch r f v t1' t2'+         Nothing        -> matchNormal v  checkSingleMatch :: (CompileErrorM m, TypeResolver r) =>   r -> ParamFilters -> Variance ->@@ -399,7 +405,7 @@   | v == Contravariant = do     ps2' <- trRefines r t2 n1     checkInstanceToInstance r f Contravariant t1 (TypeInstance n1 ps2')-  | otherwise = compileErrorM $ "Category " ++ show n2 ++ " is required but got " ++ show n2+  | otherwise = compileErrorM $ "Category " ++ show n2 ++ " is required but got " ++ show n1  checkParamToInstance :: (CompileErrorM m, TypeResolver r) =>   r -> ParamFilters -> Variance -> ParamName -> TypeInstance -> m (MergeTree InferredTypeGuess)
tests/.zeolite-module view
@@ -14,8 +14,25 @@     name: META_VAR     expression: $ExprLookup[INT_EXPR]$*5   }+  expression_macro {+    name: USES_RECURSIVE+    expression: 7 * $ExprLookup[RECURSIVE_MACRO1]$+  }+  expression_macro {+    name: RECURSIVE_MACRO1+    expression: 100 + $ExprLookup[RECURSIVE_MACRO2]$+  }+  expression_macro {+    name: RECURSIVE_MACRO2+    expression: $ExprLookup[RECURSIVE_MACRO3]$ - 200+  }+  expression_macro {+    name: RECURSIVE_MACRO3+    expression: $ExprLookup[RECURSIVE_MACRO1]$+  } ] private_deps: [+  "lib/testing"   "visibility"   "visibility2" ]
− tests/assignments.0rt
@@ -1,54 +0,0 @@-/* ------------------------------------------------------------------------------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 "overwrite arg" {-  error-  require "arg"-}--define Test {-  @type call (Int) -> ()-  call (arg) {-    arg <- 2-  }--  run () {}-}--concrete Test {-  @type run () -> ()-}---testcase "self in @category function" {-  error-  require "self"-}--define Test {-  @category call () -> ()-  call () {-    Test value <- self-  }--  run () {}-}--concrete Test {-  @type run () -> ()-}
+ tests/bad-path/.zeolite-module view
@@ -0,0 +1,2 @@+path: "/dev/null"+mode: incremental {}
+ tests/bad-path/README.md view
@@ -0,0 +1,19 @@+# Bad Path in `.zeolite-module`++Compiling this module should **always fail**. It tests that a mismatch between+`root`/`path` from `.zeolite-module` and the path to the same `.zeolite-module`+causes an error.++To compile:++```shell+ZEOLITE_PATH=$(zeolite --get-path)+zeolite -p $ZEOLITE_PATH -r tests/bad-path+```++The compiler errors should look something like this:++```text+Zeolite execution failed:+  Expected module path from /home/user/zeolite/tests/bad-path/.zeolite-module to match .zeolite-module location but got /dev/null (resolved from root: "" and path: "/dev/null")+```
tests/builtin-types.0rt view
@@ -17,1058 +17,790 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "not true" {-  success Test.run()-}--define Test {-  run () {-    if (!true) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "reduce Bool" {-  success Test.run()-}--define Test {-  run () {-    if (!present(reduce<Bool,Bool>(true))) {-      fail("Failed")-    }-    if (!present(reduce<Bool,AsBool>(true))) {-      fail("Failed")-    }-    if (present(reduce<Bool,AsChar>(true))) {-      fail("Failed")-    }-    if (!present(reduce<Bool,AsInt>(true))) {-      fail("Failed")-    }-    if (!present(reduce<Bool,AsFloat>(true))) {-      fail("Failed")-    }-    if (!present(reduce<Bool,Formatted>(true))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "reduce Char" {-  success Test.run()-}--define Test {-  run () {-    if (!present(reduce<Char,Char>('a'))) {-      fail("Failed")-    }-    if (!present(reduce<Char,AsBool>('a'))) {-      fail("Failed")-    }-    if (!present(reduce<Char,AsChar>('a'))) {-      fail("Failed")-    }-    if (!present(reduce<Char,AsInt>('a'))) {-      fail("Failed")-    }-    if (!present(reduce<Char,AsFloat>('a'))) {-      fail("Failed")-    }-    if (!present(reduce<Char,Formatted>('a'))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "reduce Int" {-  success Test.run()-}--define Test {-  run () {-    if (!present(reduce<Int,Int>(1))) {-      fail("Failed")-    }-    if (!present(reduce<Int,AsBool>(1))) {-      fail("Failed")-    }-    if (!present(reduce<Int,AsChar>(1))) {-      fail("Failed")-    }-    if (!present(reduce<Int,AsInt>(1))) {-      fail("Failed")-    }-    if (!present(reduce<Int,AsFloat>(1))) {-      fail("Failed")-    }-    if (!present(reduce<Int,Formatted>(1))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "reduce Float" {-  success Test.run()-}--define Test {-  run () {-    if (!present(reduce<Float,Float>(1.0))) {-      fail("Failed")-    }-    if (!present(reduce<Float,AsBool>(1.0))) {-      fail("Failed")-    }-    if (present(reduce<Float,AsChar>(1.0))) {-      fail("Failed")-    }-    if (!present(reduce<Float,AsInt>(1.0))) {-      fail("Failed")-    }-    if (!present(reduce<Float,AsFloat>(1.0))) {-      fail("Failed")-    }-    if (!present(reduce<Float,Formatted>(1.0))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "reduce String" {-  success Test.run()-}--define Test {-  run () {-    if (!present(reduce<String,String>("a"))) {-      fail("Failed")-    }-    if (!present(reduce<String,AsBool>("a"))) {-      fail("Failed")-    }-    if (present(reduce<String,AsChar>("a"))) {-      fail("Failed")-    }-    if (present(reduce<String,AsInt>("a"))) {-      fail("Failed")-    }-    if (present(reduce<String,AsFloat>("a"))) {-      fail("Failed")-    }-    if (!present(reduce<String,Formatted>("a"))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "reduce ReadPosition success" {-  success Test.run()-}--define Test {-  run () {-    if (!present(reduce<ReadPosition<Char>,ReadPosition<Formatted>>("x"))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "reduce ReadPosition fail" {-  success Test.run()-}--define Test {-  run () {-    if (present(reduce<ReadPosition<Formatted>,ReadPosition<Char>>("x"))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String LessThan" {-  success Test.run()-}--define Test {-  run () {-    if (!("x" `String.lessThan` "y")) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Bool Equals" {-  success Test.run()-}--define Test {-  run () {-    if (!(true `Bool.equals` true)) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String Equals" {-  success Test.run()-}--define Test {-  run () {-    if (!("x" `String.equals` "x")) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String Builder" {-  success Test.run()-}--define Test {-  run () {-    Builder<String> builder <- String.builder()-    \ Testing.check<?>(builder.build(),"")-    \ Testing.check<?>(builder.append("xyz").build(),"xyz")-    \ Testing.check<?>(builder.append("123").build(),"xyz123")-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Char LessThan" {-  success Test.run()-}--define Test {-  run () {-    if (!('x' `Char.lessThan` 'y')) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Char Equals" {-  success Test.run()-}--define Test {-  run () {-    if (!('x' `Char.equals` 'x')) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int LessThan" {-  success Test.run()-}--define Test {-  run () {-    if (!(1 `Int.lessThan` 2)) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int Equals" {-  success Test.run()-}--define Test {-  run () {-    if (!(1 `Int.equals` 1)) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Float LessThan" {-  success Test.run()-}--define Test {-  run () {-    if (!(1.0 `Float.lessThan` 2.0)) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Float Equals" {-  success Test.run()-}--define Test {-  run () {-    if (!(1.0 `Float.equals` 1.0)) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Bool is shared" {-  success Test.run()-}--define Test {-  run () {-    Bool value1 <- true-    // Shared because true and false are boxed constants.-    weak Bool value2 <- value1-    if (!present(strong(value2))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String is shared" {-  success Test.run()-}--define Test {-  run () {-    String value1 <- "x"-    weak String value2 <- value1-    if (!present(strong(value2))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String Builder is not lazy" {-  success Test.run()-}--define Test {-  run () {-    optional String value1 <- "value"-    weak String value2 <- value1-    if (!present(strong(value2))) {-      fail("Failed")-    }-    Builder<String> builder <- String.builder().append(require(value1))-    value1 <- empty-    if (present(strong(value2))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Char is not shared" {-  success Test.run()-}--define Test {-  run () {-    Char value1 <- 'x'-    weak Char value2 <- value1-    if (present(strong(value2))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int is not shared" {-  success Test.run()-}--define Test {-  run () {-    Int value1 <- 1-    weak Int value2 <- value1-    if (present(strong(value2))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Float is not shared" {-  success Test.run()-}--define Test {-  run () {-    Float value1 <- 1.1-    weak Float value2 <- value1-    if (present(strong(value2))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String Formatted" {-  success Test.run()-}--define Test {-  run () {-    String s <- ("x").formatted()-    if (s != "x") {-      fail(s)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Char Formatted" {-  success Test.run()-}--define Test {-  run () {-    String s <- ('x').formatted()-    if (s != "x") {-      fail(s)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Char octal Formatted" {-  success Test.run()-}--define Test {-  run () {-    String s <- ('\170').formatted()-    if (s != "x") {-      fail(s)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Char hex Formatted" {-  success Test.run()-}--define Test {-  run () {-    String s <- ('\x78').formatted()-    if (s != "x") {-      fail(s)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int Formatted" {-  success Test.run()-}--define Test {-  run () {-    String s <- (1).formatted()-    if (s != "1") {-      fail(s)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int hex Formatted" {-  success Test.run()-}--define Test {-  run () {-    String s <- (\x0010).formatted()-    if (s != "16") {-      fail(s)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Float Formatted" {-  success Test.run()-}--define Test {-  run () {-    String s <- (1.1).formatted()-    if (s != "1.1") {  // precision might vary-      fail(s)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Bool Formatted" {-  success Test.run()-}--define Test {-  run () {-    String s <- (false).formatted()-    if (s != "false") {-      fail(s)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String access" {-  success Test.run()-}--define Test {-  run () {-    String s <- "abcde"-    Char c <- s.readPosition(3)-    if (c != 'd') {-      fail(c)-    }-    Int size <- s.readSize()-    if (size != 5) {-      fail(size)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String access negative" {-  crash Test.run()-  require "-10"-  require "bounds"-}--define Test {-  run () {-    \ ("abc").readPosition(-10)-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String access past end" {-  crash Test.run()-  require "100"-  require "bounds"-}--define Test {-  run () {-    \ ("abc").readPosition(100)-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String subsequence" {-  success Test.run()-}--define Test {-  run () {-    String s <- "abcde"-    String s2 <- s.subSequence(1,3)-    if (s2 != "bcd") {-      fail(s2)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String empty subsequence at end" {-  success Test.run()-}--define Test {-  run () {-    String s <- ""-    String s2 <- s.subSequence(0,0)-    if (s2 != "") {-      fail(s2)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String subsequence past end" {-  crash Test.run()-  require "100"-  require "size"-}--define Test {-  run () {-    \ ("abc").subSequence(1,100)-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int max is accurate" {-  success Test.run()-}--define Test {-  run () {-    Int x <- 9223372036854775807 - 1-    if (x != 9223372036854775806) {-      fail(x)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int min is accurate" {-  success Test.run()-}--define Test {-  run () {-    Int x <- -9223372036854775806 + 1-    if (x != -9223372036854775805) {-      fail(x)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int unsigned works properly" {-  success Test.run()-}--define Test {-  run () {-    if (\xffffffffffffffff != -1) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int literal too large" {-  error-  require "9223372036854775808"-  require "max"-}--define Test {-  run () {-    \ 9223372036854775808-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int unsigned literal too large" {-  error-  require "18446744073709551616"-  require "max"-}--define Test {-  run () {-    \ \x10000000000000000-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int literal too small" {-  error-  require "-9223372036854775807"-  require "min"-}--define Test {-  run () {-    \ -9223372036854775807-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Float exponent does not cross whitespace" {-  success Test.run()-}--concrete E10 {-  @type create () -> (E10)-}--define E10 {-  create () {-    return E10{ }-  }-}--define Test {-  run () {-    Float x <- 1.2345-    E10 y <- E10.create()-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String allows null" {-  success Test.run()-}--define Test {-  run () {-    if ("abc\x00def" == "abc") {-      fail("Failed")-    }-    if (("abc\x00def").readPosition(4) != 'd') {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Bool conversions" {-  success Test.run()-}--define Test {-  run () {-    Bool b1 <- (false).asBool()-    if (b1 != false) {-      fail(b1)-    }-    Bool b2 <- (true).asBool()-    if (b2 != true) {-      fail(b2)-    }-    Int i <- (true).asInt()-    if (i != 1) {-      fail(i)-    }-    Float f <- (true).asFloat()-    if (f != 1.0) {-      fail(f)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Char conversions" {-  success Test.run()-}--define Test {-  run () {-    Bool b1 <- ('\x00').asBool()-    if (b1 != false) {-      fail(b1)-    }-    Bool b2 <- ('\x10').asBool()-    if (b2 != true) {-      fail(b2)-    }-    Char c <- ('a').asChar()-    if (c != 'a') {-      fail(c)-    }-    Int i <- ('\x10').asInt()-    if (i != 16) {-      fail(i)-    }-    Float f <- ('\x10').asFloat()-    if (f != 16.0) {-      fail(f)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Int conversions" {-  success Test.run()-}--define Test {-  run () {-    Bool b1 <- (0).asBool()-    if (b1 != false) {-      fail(b1)-    }-    Bool b2 <- (16).asBool()-    if (b2 != true) {-      fail(b2)-    }-    Char c <- (97).asChar()-    if (c != 'a') {-      fail(c)-    }-    Int i <- (16).asInt()-    if (i != 16) {-      fail(i)-    }-    Float f <- (16).asFloat()-    if (f != 16.0) {-      fail(f)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "Float conversions" {-  success Test.run()-}--define Test {-  run () {-    Bool b1 <- (0.0).asBool()-    if (b1 != false) {-      fail(b1)-    }-    Bool b2 <- (16.0).asBool()-    if (b2 != true) {-      fail(b2)-    }-    Int i <- (16.0).asInt()-    if (i != 16) {-      fail(i)-    }-    Float f <- (16.0).asFloat()-    if (f != 16.0) {-      fail(f)-    }-  }-}--concrete Test {-  @type run () -> ()-}---testcase "String conversions" {-  success Test.run()-}--define Test {-  run () {-    Bool b1 <- ("").asBool()-    if (b1 != false) {-      fail(b1)-    }-    Bool b2 <- ("\x00").asBool()-    if (b2 != true) {-      fail(b2)-    }-  }-}--concrete Test {-  @type run () -> ()+  success+}++unittest test {+  if (!true) {+    fail("Failed")+  }+}+++testcase "reduce Bool" {+  success+}++unittest bool {+  if (!present(reduce<Bool,Bool>(true))) {+    fail("Failed")+  }+}++unittest asBool {+  if (!present(reduce<Bool,AsBool>(true))) {+    fail("Failed")+  }+}++unittest asChar {+  if (present(reduce<Bool,AsChar>(true))) {+    fail("Failed")+  }+}++unittest asInt {+  if (!present(reduce<Bool,AsInt>(true))) {+    fail("Failed")+  }+}++unittest asFloat {+  if (!present(reduce<Bool,AsFloat>(true))) {+    fail("Failed")+  }+}++unittest formatted {+  if (!present(reduce<Bool,Formatted>(true))) {+    fail("Failed")+  }+}+++testcase "reduce Char" {+  success+}++unittest char {+  if (!present(reduce<Char,Char>('a'))) {+    fail("Failed")+  }+}++unittest asBool {+  if (!present(reduce<Char,AsBool>('a'))) {+    fail("Failed")+  }+}++unittest asChar {+  if (!present(reduce<Char,AsChar>('a'))) {+    fail("Failed")+  }+}++unittest asInt {+  if (!present(reduce<Char,AsInt>('a'))) {+    fail("Failed")+  }+}++unittest asFloat {+  if (!present(reduce<Char,AsFloat>('a'))) {+    fail("Failed")+  }+}++unittest formatted {+  if (!present(reduce<Char,Formatted>('a'))) {+    fail("Failed")+  }+}+++testcase "reduce Int" {+  success+}++unittest int {+  if (!present(reduce<Int,Int>(1))) {+    fail("Failed")+  }+}++unittest asBool {+  if (!present(reduce<Int,AsBool>(1))) {+    fail("Failed")+  }+}++unittest asChar {+  if (!present(reduce<Int,AsChar>(1))) {+    fail("Failed")+  }+}++unittest asInt {+  if (!present(reduce<Int,AsInt>(1))) {+    fail("Failed")+  }+}++unittest asFloat {+  if (!present(reduce<Int,AsFloat>(1))) {+    fail("Failed")+  }+}++unittest formatted {+  if (!present(reduce<Int,Formatted>(1))) {+    fail("Failed")+  }+}+++testcase "reduce Float" {+  success+}++unittest float {+  if (!present(reduce<Float,Float>(1.0))) {+    fail("Failed")+  }+}++unittest asBool {+  if (!present(reduce<Float,AsBool>(1.0))) {+    fail("Failed")+  }+}++unittest asChar {+  if (present(reduce<Float,AsChar>(1.0))) {+    fail("Failed")+  }+}++unittest asInt {+  if (!present(reduce<Float,AsInt>(1.0))) {+    fail("Failed")+  }+}++unittest asFloat {+  if (!present(reduce<Float,AsFloat>(1.0))) {+    fail("Failed")+  }+}++unittest formatted {+  if (!present(reduce<Float,Formatted>(1.0))) {+    fail("Failed")+  }+}+++testcase "reduce String" {+  success+}++unittest string {+  if (!present(reduce<String,String>("a"))) {+    fail("Failed")+  }+}++unittest asBool {+  if (!present(reduce<String,AsBool>("a"))) {+    fail("Failed")+  }+}++unittest asChar {+  if (present(reduce<String,AsChar>("a"))) {+    fail("Failed")+  }+}++unittest asInt {+  if (present(reduce<String,AsInt>("a"))) {+    fail("Failed")+  }+}++unittest asFloar {+  if (present(reduce<String,AsFloat>("a"))) {+    fail("Failed")+  }+}++unittest formatted {+  if (!present(reduce<String,Formatted>("a"))) {+    fail("Failed")+  }+}+++testcase "reduce ReadPosition" {+  success+}++unittest success {+  if (!present(reduce<ReadPosition<Char>,ReadPosition<Formatted>>("x"))) {+    fail("Failed")+  }+}++unittest failure {+  if (present(reduce<ReadPosition<Formatted>,ReadPosition<Char>>("x"))) {+    fail("Failed")+  }+}+++testcase "interface implementations" {+  success+}++unittest stringLessThan {+  if (!("x" `String.lessThan` "y")) {+    fail("Failed")+  }+}++unittest boolEquals {+  if (!(true `Bool.equals` true)) {+    fail("Failed")+  }+}++unittest stringEquals {+  if (!("x" `String.equals` "x")) {+    fail("Failed")+  }+}++unittest stringBuilder {+  Builder<String> builder <- String.builder()+  \ Testing.checkEquals<?>(builder.build(),"")+  \ Testing.checkEquals<?>(builder.append("xyz").build(),"xyz")+  \ Testing.checkEquals<?>(builder.append("123").build(),"xyz123")+}++unittest charLessThan {+  if (!('x' `Char.lessThan` 'y')) {+    fail("Failed")+  }+}++unittest charEquals {+  if (!('x' `Char.equals` 'x')) {+    fail("Failed")+  }+}++unittest intLessThan {+  if (!(1 `Int.lessThan` 2)) {+    fail("Failed")+  }+}++unittest intEquals {+  if (!(1 `Int.equals` 1)) {+    fail("Failed")+  }+}++unittest floatLessThan {+  if (!(1.0 `Float.lessThan` 2.0)) {+    fail("Failed")+  }+}++unittest floatEquals {+  if (!(1.0 `Float.equals` 1.0)) {+    fail("Failed")+  }+}++unittest stringFormatted {+  String s <- ("x").formatted()+  if (s != "x") {+    fail(s)+  }+}++unittest charFormatted {+  String s <- ('x').formatted()+  if (s != "x") {+    fail(s)+  }+}++unittest charFormattedOct {+  String s <- ('\170').formatted()+  if (s != "x") {+    fail(s)+  }+}++unittest charFormattedHex {+  String s <- ('\x78').formatted()+  if (s != "x") {+    fail(s)+  }+}++unittest intFormatted {+  String s <- (1).formatted()+  if (s != "1") {+    fail(s)+  }+}++unittest intFormattedHex {+  String s <- (\x0010).formatted()+  if (s != "16") {+    fail(s)+  }+}++unittest floatFormatted {+  String s <- (1.1).formatted()+  if (s != "1.1") {  // precision might vary+    fail(s)+  }+}++unittest boolFormatted {+  String s <- (false).formatted()+  if (s != "false") {+    fail(s)+  }+}+++testcase "reference sharing" {+  success+}++unittest boolShared {+  Bool value1 <- true+  // Shared because true and false are boxed constants.+  weak Bool value2 <- value1+  if (!present(strong(value2))) {+    fail("Failed")+  }+}++unittest stringShared {+  String value1 <- "x"+  weak String value2 <- value1+  if (!present(strong(value2))) {+    fail("Failed")+  }+}++unittest charNotShared {+  Char value1 <- 'x'+  weak Char value2 <- value1+  if (present(strong(value2))) {+    fail("Failed")+  }+}++unittest intNotShared {+  Int value1 <- 1+  weak Int value2 <- value1+  if (present(strong(value2))) {+    fail("Failed")+  }+}++unittest floatNotShared {+  Float value1 <- 1.1+  weak Float value2 <- value1+  if (present(strong(value2))) {+    fail("Failed")+  }+}+++testcase "String stuff" {+  success+}++unittest builderNotLazy {+  optional String value1 <- "value"+  weak String value2 <- value1+  if (!present(strong(value2))) {+    fail("Failed")+  }+  Builder<String> builder <- String.builder().append(require(value1))+  value1 <- empty+  if (present(strong(value2))) {+    fail("Failed")+  }+}++unittest simpleAccess {+  String s <- "abcde"+  Char c <- s.readPosition(3)+  if (c != 'd') {+    fail(c)+  }+  Int size <- s.readSize()+  if (size != 5) {+    fail(size)+  }+}++unittest subsequence {+  String s <- "abcde"+  String s2 <- s.subSequence(1,3)+  if (s2 != "bcd") {+    fail(s2)+  }+}++unittest emptySubsequence {+  String s <- ""+  String s2 <- s.subSequence(0,0)+  if (s2 != "") {+    fail(s2)+  }+}++unittest nullChar {+  if ("abc\x00def" == "abc") {+    fail("Failed")+  }+  if (("abc\x00def").readPosition(4) != 'd') {+    fail("Failed")+  }+}+++testcase "String access negative" {+  crash+  require "-10"+  require "bounds"+}++unittest test {+  \ Test.run()+}++define Test {+  run () {+    \ ("abc").readPosition(-10)+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "String access past end" {+  crash+  require "100"+  require "bounds"+}++unittest test {+  \ Test.run()+}++define Test {+  run () {+    \ ("abc").readPosition(100)+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "String subsequence past end" {+  crash+  require "100"+  require "size"+}++unittest test {+  \ Test.run()+}++define Test {+  run () {+    \ ("abc").subSequence(1,100)+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "Int stuff" {+  success+}++unittest accurateMax {+  Int x <- 9223372036854775807 - 1+  if (x != 9223372036854775806) {+    fail(x)+  }+}++unittest accurateMin {+  Int x <- -9223372036854775806 + 1+  if (x != -9223372036854775805) {+    fail(x)+  }+}++unittest hexUnsigned {+  if (\xffffffffffffffff != -1) {+    fail("Failed")+  }+}+++testcase "Int literal too large" {+  error+  require "9223372036854775808"+  require "max"+}++define Test {+  run () {+    \ 9223372036854775808+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "Int unsigned literal too large" {+  error+  require "18446744073709551616"+  require "max"+}++define Test {+  run () {+    \ \x10000000000000000+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "Int literal too small" {+  error+  require "-9223372036854775807"+  require "min"+}++define Test {+  run () {+    \ -9223372036854775807+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "Float exponent does not cross whitespace" {+  success+}++unittest test {+  \ Test.run()+}++concrete E10 {+  @type create () -> (E10)+}++define E10 {+  create () {+    return E10{ }+  }+}++define Test {+  run () {+    Float x <- 1.2345+    E10 y <- E10.create()+  }+}++concrete Test {+  @type run () -> ()+}+++testcase "Bool conversions" {+  success+}++unittest falseAsBool {+  Bool b1 <- (false).asBool()+  if (b1 != false) {+    fail(b1)+  }+}++unittest trueAsBool {+  Bool b2 <- (true).asBool()+  if (b2 != true) {+    fail(b2)+  }+}++unittest asInt {+  Int i <- (true).asInt()+  if (i != 1) {+    fail(i)+  }+}++unittest asFloat {+  Float f <- (true).asFloat()+  if (f != 1.0) {+    fail(f)+  }+}+++testcase "Char conversions" {+  success+}++unittest nullAsBool {+  Bool b1 <- ('\x00').asBool()+  if (b1 != false) {+    fail(b1)+  }+}++unittest nonNullAsBool {+  Bool b2 <- ('\x10').asBool()+  if (b2 != true) {+    fail(b2)+  }+}++unittest asChar {+  Char c <- ('a').asChar()+  if (c != 'a') {+    fail(c)+  }+}++unittest asInt {+  Int i <- ('\x10').asInt()+  if (i != 16) {+    fail(i)+  }+}++unittest asFloat {+  Float f <- ('\x10').asFloat()+  if (f != 16.0) {+    fail(f)+  }+}+++testcase "Int conversions" {+  success+}++unittest zeroAsBool {+  Bool b1 <- (0).asBool()+  if (b1 != false) {+    fail(b1)+  }+}++unittest nonZeroAsBool {+  Bool b2 <- (16).asBool()+  if (b2 != true) {+    fail(b2)+  }+}++unittest asChar {+  Char c <- (97).asChar()+  if (c != 'a') {+    fail(c)+  }+}++unittest asInt {+  Int i <- (16).asInt()+  if (i != 16) {+    fail(i)+  }+}++unittest asFloat {+  Float f <- (16).asFloat()+  if (f != 16.0) {+    fail(f)+  }+}+++testcase "Float conversions" {+  success+}++unittest zeroAsBool {+  Bool b1 <- (0.0).asBool()+  if (b1 != false) {+    fail(b1)+  }+}++unittest nonZeroAsBool {+  Bool b2 <- (16.0).asBool()+  if (b2 != true) {+    fail(b2)+  }+}++unittest asInt {+  Int i <- (16.0).asInt()+  if (i != 16) {+    fail(i)+  }+}++unittest asFloat {+  Float f <- (16.0).asFloat()+  if (f != 16.0) {+    fail(f)+  }+}+++testcase "String conversions" {+  success+}++unittest emptyAsBool {+  Bool b1 <- ("").asBool()+  if (b1 != false) {+    fail(b1)+  }+}++unittest singleNullAsBool {+  Bool b2 <- ("\x00").asBool()+  if (b2 != true) {+    fail(b2)+  } }
tests/check-defs/README.md view
@@ -2,7 +2,7 @@  Compiling this module should **always fail**. It tests a compiler check that ensures that `concrete` categories have exactly one definition or are declared-in the `external:` section of `.zeolite-module`.+in a `category_source` in the `extra_files:` section of `.zeolite-module`.  To compile: 
tests/cli-tests.sh view
@@ -48,6 +48,16 @@ }  +test_bad_path() {+  local output=$(do_zeolite -p "$ZEOLITE_PATH" -r tests/bad-path -f || true)+  if ! echo "$output" | egrep -q 'bad-path/\.zeolite-module .+ /dev/null'; then+    show_message 'Expected path error from tests/bad-path:'+    echo "$output" 1>&2+    return 1+  fi+}++ test_check_defs() {   local output=$(do_zeolite -p "$ZEOLITE_PATH" -r tests/check-defs -f || true)   if ! echo "$output" | egrep -q 'Type .+ is defined 2 times'; then@@ -319,6 +329,7 @@ }  ALL_TESTS=(+  test_bad_path   test_check_defs   test_tests_only   test_tests_only2
tests/conditionals.0rt view
@@ -17,12 +17,10 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "assign if/elif/else" {-  success Test.run()+  compiles } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value)   process () (value) {     if (false) {@@ -33,22 +31,16 @@       value <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "return if/elif/else" {-  success Test.run()+  compiles } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value)   process () {     if (false) {@@ -59,13 +51,9 @@       return empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "assign if/elif condition" {@@ -73,9 +61,7 @@   require "value.+before return" } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value)   process () (value) {     if (present((value <- empty))) {@@ -84,13 +70,9 @@       value <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "different in if and else" {@@ -99,9 +81,7 @@   require "value2.+before return" } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value,optional Value)   process () (value1,value2) {     if (false) {@@ -110,13 +90,9 @@       value2 <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "missing in if" {@@ -124,9 +100,7 @@   require "value.+before return" } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value)   process () (value) {     if (false) {@@ -136,13 +110,9 @@       value <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "missing in elif" {@@ -150,9 +120,7 @@   require "value.+before return" } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value)   process () (value) {     if (false) {@@ -162,13 +130,9 @@       value <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "missing in else" {@@ -176,9 +140,7 @@   require "value.+before return" } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value)   process () (value) {     if (false) {@@ -188,23 +150,18 @@     } else {     }   }--  run () {} } -concrete Test {-  @type run () -> ()-} +concrete Value {} + testcase "missing in implicit else" {   error   require "value.+before return" } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value)   process () (value) {     if (false) {@@ -213,61 +170,43 @@       value <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "crash in if" {-  crash Test.run()+  crash   require "empty" } -define Test {-  run () {-    optional Bool test <- empty-    if (require(test)) {-      // empty-    }+unittest test {+  optional Bool test <- empty+  if (require(test)) {+    // empty   } } -concrete Test {-  @type run () -> ()-} - testcase "crash in elif" {-  crash Test.run()+  crash   require "empty" } -define Test {-  run () {-    optional Bool test <- empty-    if (false) {-    } elif (require(test)) {-      // empty-    }+unittest test {+  optional Bool test <- empty+  if (false) {+  } elif (require(test)) {+    // empty   } } -concrete Test {-  @type run () -> ()-} - testcase "multi assign if/elif/else" {-  success Test.run()+  compiles } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value,optional Value)   process () (value1,value2) {     if (false) {@@ -281,13 +220,9 @@       value2 <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "multi missing in if" {@@ -295,9 +230,7 @@   require "value2" } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value,optional Value)   process () (value1,value2) {     if (false) {@@ -310,13 +243,9 @@       value2 <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "multi missing in elif" {@@ -324,9 +253,7 @@   require "value2" } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value,optional Value)   process () (value1,value2) {     if (false) {@@ -339,13 +266,9 @@       value2 <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "multi missing in else" {@@ -353,9 +276,7 @@   require "value2" } -@value interface Value {}--define Test {+define Value {   @value process () -> (optional Value,optional Value)   process () (value1,value2) {     if (false) {@@ -368,19 +289,27 @@       value1 <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Value {}   testcase "cleanup before return in if" {-  success Test.run()+  success } +unittest test {+  Value value <- Value.create()+  Int value1 <- value.call()+  if (value1 != 2) {+    fail(value1)+  }+  Int value2 <- value.get()+  if (value2 != 3) {+    fail(value2)+  }+}+ concrete Value {   @type create () -> (Value)   @value call () -> (Int)@@ -409,22 +338,4 @@   get () {     return value   }-}--define Test {-  run () {-    Value value <- Value.create()-    Int value1 <- value.call()-    if (value1 != 2) {-      fail(value1)-    }-    Int value2 <- value.get()-    if (value2 != 3) {-      fail(value2)-    }-  }-}--concrete Test {-  @type run () -> () }
tests/expr-lookup.0rt view
@@ -21,46 +21,28 @@   require "UNKNOWN_STRING .+not defined" } -define Test {-  run () {-    String value <- $ExprLookup[UNKNOWN_STRING]$-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  String value <- $ExprLookup[UNKNOWN_STRING]$ }   testcase "MODULE_PATH is absolute" {-  crash Test.run()+  crash   require "Failed condition: /.+/tests" } -define Test {-  run () {-    fail($ExprLookup[MODULE_PATH]$)-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  fail($ExprLookup[MODULE_PATH]$) }   testcase "MODULE_PATH from regular source" {-  crash Test.run()+  crash   require "Failed condition: /.+/tests" } -define Test {-  run () {-    fail(ExprLookup.modulePath())-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  fail(ExprLookup.modulePath()) }  @@ -69,72 +51,55 @@   require "String.+Int" } -define Test {-  run () {-    Int value <- $ExprLookup[MODULE_PATH]$-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  Int value <- $ExprLookup[MODULE_PATH]$ }   testcase "macro used inline in expressions" {-  crash Test.run()+  crash   require "Failed condition: /.+/tests is the path" } -define Test {-  run () {-    fail($ExprLookup[MODULE_PATH]$ + " is the path")-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  fail($ExprLookup[MODULE_PATH]$ + " is the path") }   testcase "constant defined in .zeolite-module" {-  success Test.run()-}--define Test {-  run () {-    \ Testing.check<?>($ExprLookup[INT_EXPR]$,4)-  }+  success } -concrete Test {-  @type run () -> ()+unittest test {+  \ Testing.checkEquals<?>($ExprLookup[INT_EXPR]$,4)+  // Use it a second time to ensure that reserving the macro name doesn't+  // carry over to the next statement.+  \ $ExprLookup[INT_EXPR]$ }   testcase "constant defined in .zeolite-module from regular source" {-  success Test.run()-}--define Test {-  run () {-    \ Testing.check<?>(ExprLookup.intExpr(),4)-  }+  success } -concrete Test {-  @type run () -> ()+unittest test {+  \ Testing.checkEquals<?>(ExprLookup.intExpr(),4) }   testcase "in context defined in .zeolite-module" {-  success Test.run()+  success } +unittest test {+  \ Test.run()+}+ define Test {   @category String macroLocalVar <- "hello"    run () {-    \ Testing.check<?>($ExprLookup[LOCAL_VAR]$,"hello")+    \ Testing.checkEquals<?>($ExprLookup[LOCAL_VAR]$,"hello")   } } @@ -149,73 +114,57 @@   require "macroLocalVar" } -define Test {-  run () {-    String value <- $ExprLookup[LOCAL_VAR]$-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  String value <- $ExprLookup[LOCAL_VAR]$ }   testcase "in context defined in .zeolite-module from regular source" {-  success Test.run()-}--define Test {-  run () {-    \ Testing.check<?>(ExprLookup.localVar(),99)-  }+  success } -concrete Test {-  @type run () -> ()+unittest test {+  \ Testing.checkEquals<?>(ExprLookup.localVar(),99) }   testcase "nested expression defined in .zeolite-module" {-  success Test.run()-}--define Test {-  run () {-    \ Testing.check<?>($ExprLookup[META_VAR]$,20)-  }+  success } -concrete Test {-  @type run () -> ()+unittest test {+  \ Testing.checkEquals<?>($ExprLookup[META_VAR]$,20) }   testcase "function called on expression" {-  success Test.run()-}--define Test {-  run () {-    \ Testing.check<?>($ExprLookup[INT_EXPR]$.formatted(),"4")-  }+  success } -concrete Test {-  @type run () -> ()+unittest test {+  \ Testing.checkEquals<?>($ExprLookup[INT_EXPR]$.formatted(),"4") }   testcase "source context" {-  crash Test.run()+  crash   require "tests/expr-lookup\.0rt" } -define Test {-  run () {-    fail($SourceContext$)-  }+unittest test {+  fail($SourceContext$) } -concrete Test {-  @type run () -> ()++testcase "recursive expression" {+  error+  exclude compiler "USES_RECURSIVE expanded at"+  require compiler "USES_RECURSIVE"+  require compiler "RECURSIVE_MACRO1 expanded at"+  require compiler "RECURSIVE_MACRO2 expanded at"+  require compiler "RECURSIVE_MACRO3 expanded at"+}++unittest test {+  String value <- $ExprLookup[USES_RECURSIVE]$ }
tests/failure.0rt view
@@ -17,33 +17,37 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "fail builtin" {-  crash Test.run()+  crash   require stderr "Failed"+  require stderr "failedReturn" } -define Test {+unittest test {+  Int value <- Test:failedReturn()+}++concrete Test {   @category failedReturn () -> (Int)+}++define Test {   failedReturn () {     fail("Failed")   }--  run () {-    Int value <- failedReturn()-  } } -concrete Test {-  @type run () -> ()-}  - testcase "wrong type for fail" {   error   require "fail"   require "Formatted" } +unittest test {+  fail(Value.create())+}+ concrete Value {   @type create () -> (Value) }@@ -54,28 +58,12 @@   } } -define Test {-  run () {-    fail(Value.create())-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "require empty" {-  crash Test.run()+  crash   require stderr "require.+empty" } -define Test {-  run () {-    \ require(empty)-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  \ require(empty) }
tests/filters.0rt view
@@ -17,9 +17,13 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "external filter not applied in @category" {-  success Test.run()+  success } +unittest test {+  \ Value:something<Bool>()+}+ concrete Value<#x> {   #x defines LessThan<#x> @@ -30,36 +34,35 @@   something () {} } -define Test {-  run () {-    \ Value:something<Bool>()-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "category param bounded on both sides" {   error   require compiler "#x.+bound"+  require compiler "[Uu]pper.+ \[Type1&Type2\]"+  require compiler "[Ll]ower.+ \[Type3\|Type4\]" }  @value interface Type1 {}  @value interface Type2 {} +@value interface Type3 {}++@value interface Type4 {}+ @value interface Value<#x> {   #x requires Type1-  #x allows   Type2+  #x requires Type2+  #x allows   Type3+  #x allows   Type4 }   testcase "implicit bound from reversing another filter" {   error   require compiler "#x.+bound"-  require compiler "#x allows #y"+  require compiler "[Uu]pper.+ Type"+  require compiler "[Ll]ower.+ #y" }  @value interface Type {}@@ -71,7 +74,7 @@   testcase "defines filter is not an upper bound" {-  success empty+  compiles }  @type interface Type1 {}@@ -85,7 +88,7 @@   testcase "defines filter is not a lower bound" {-  success empty+  compiles }  @type interface Type1 {}
tests/function-calls.0rt view
@@ -17,9 +17,14 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "converted call" {-  success Test.run()+  success } +unittest test {+  Value value <- Value.create()+  \ value.Base.call()+}+ @value interface Base {   call () -> () }@@ -38,23 +43,17 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    \ value.Base.call()-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "converted call bad type" {   error   require "Base" } +unittest test {+  Value value <- Value.create()+  \ value.Base.call()+}+ @value interface Base {   call () -> () }@@ -72,23 +71,17 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    \ value.Base.call()-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "call from union" {   error   require "\[Base\|Value\]" } +unittest test {+  [Base|Value] value <- Value.create()+  \ value.call()+}+ @value interface Base {   call () -> () }@@ -107,20 +100,14 @@   } } -define Test {-  run () {-    [Base|Value] value <- Value.create()-    \ value.call()-  }-} -concrete Test {-  @type run () -> ()+testcase "call from union with conversion" {+  success } --testcase "call from union with conversion" {-  success Test.run()+unittest test {+  [Base|Value] value <- Value.create()+  \ value.Base.call() }  @value interface Base {@@ -141,20 +128,14 @@   } } -define Test {-  run () {-    [Base|Value] value <- Value.create()-    \ value.Base.call()-  }-} -concrete Test {-  @type run () -> ()+testcase "call from intersect" {+  success } --testcase "call from intersect" {-  success Test.run()+unittest test {+  [Base1&Base2] value <- Value.create()+  \ value.call() }  @value interface Base1 {@@ -178,20 +159,14 @@   } } -define Test {-  run () {-    [Base1&Base2] value <- Value.create()-    \ value.call()-  }-} -concrete Test {-  @type run () -> ()+testcase "call from intersect with conversion" {+  success } --testcase "call from intersect with conversion" {-  success Test.run()+unittest test {+  [Base1&Base2] value <- Value.create()+  \ value.Base1.call() }  @value interface Base1 {@@ -215,20 +190,14 @@   } } -define Test {-  run () {-    [Base1&Base2] value <- Value.create()-    \ value.Base1.call()-  }-} -concrete Test {-  @type run () -> ()+testcase "call from intersect with conversion" {+  success } --testcase "call from intersect with conversion" {-  success Test.run()+unittest test {+  [Base1&Base2] value <- Value.create()+  \ value.Base1.call() }  @value interface Base1 {@@ -252,20 +221,13 @@   } } -define Test {-  run () {-    [Base1&Base2] value <- Value.create()-    \ value.Base1.call()-  }-} -concrete Test {-  @type run () -> ()+testcase "call from param type" {+  success } --testcase "call from param type" {-  success Test.run()+unittest test {+  \ Test.check<Value>() }  @type interface Base {@@ -280,24 +242,19 @@   call () {} } -define Test {+concrete Test {   @type check<#x>     #x defines Base   () -> ()+}++define Test {   check () {     \ #x.call()   }--  run () {-    \ check<Value>()-  } } -concrete Test {-  @type run () -> ()-} - testcase "call from bad param type" {   error   require "call.+param #x"@@ -313,19 +270,20 @@   check () {     \ #x.call()   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Test {}   testcase "call from param value" {-  success Test.run()+  success } +unittest test {+  Value value <- Value.create()+  \ Test.check<Value>(value)+}+ @value interface Base {   call () -> () }@@ -344,25 +302,19 @@   } } -define Test {+concrete Test {   @type check<#x>     #x requires Base   (#x) -> ()+}++define Test {   check (value) {     \ value.call()   }--  run () {-    Value value <- Value.create()-    \ check<Value>(value)-  } } -concrete Test {-  @type run () -> ()-} - testcase "call from bad param value" {   error   require "call.+param #x"@@ -378,19 +330,19 @@   check (value) {     \ value.call()   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Test {}   testcase "convert arg" {-  success Test.run()+  success } +unittest test {+  \ Test.convert(Value.create()).call()+}+ @value interface Base {   call () -> () }@@ -409,22 +361,17 @@   } } -define Test {+concrete Test {   @type convert (Value) -> (Base)+}++define Test {   convert (value) {     return value   }--  run () {-   \ convert(Value.create()).call()-  } } -concrete Test {-  @type run () -> ()-} - testcase "bad convert arg" {   error   require "does not refine Value"@@ -441,13 +388,9 @@   convert (value) {     return value   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Test {}   testcase "bad instance in param" {@@ -457,6 +400,10 @@   require "Equals" } +unittest test {+  \ Call.call<Value<Test>>()+}+ @value interface Value<#x> {   #x defines Equals<#x> }@@ -469,12 +416,32 @@   call () {} } ++testcase "overwrite arg" {+  error+  require "arg"+}+ define Test {-  run () {-    \ Call.call<Value<Test>>()+  @type call (Int) -> ()+  call (arg) {+    arg <- 2   } } -concrete Test {-  @type run () -> ()+concrete Test {}+++testcase "self in @category function" {+  error+  require "self" }++define Test {+  @category call () -> ()+  call () {+    Test value <- self+  }+}++concrete Test {}
tests/function-merging.0rt view
@@ -17,9 +17,13 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "internal merge" {-  success Test.run()+  success } +unittest test {+  \ Value.create().call().call()+}+ @value interface Interface {   call () -> (Interface) }@@ -40,17 +44,7 @@   } } -define Test {-  run () {-    \ Value.create().call().call()-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "internal merge failed" {   error   require "Interface2"@@ -79,17 +73,13 @@   } } -define Test {-  run () {}-} -concrete Test {-  @type run () -> ()+testcase "external merge" {+  success } --testcase "external merge" {-  success Test.run()+unittest test {+  \ Value.create().call().call() }  @value interface Interface {@@ -112,17 +102,7 @@   } } -define Test {-  run () {-    \ Value.create().call().call()-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "external merge failed" {   error   require "Interface2"@@ -149,12 +129,4 @@   call () {     return self   }-}--define Test {-  run () {}-}--concrete Test {-  @type run () -> () }
− tests/helpers.0rp
@@ -1,32 +0,0 @@-/* ------------------------------------------------------------------------------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]--$TestsOnly$--concrete Testing {-  @type check<#x>-    #x requires Formatted-    #x defines Equals<#x>-  (#x /*actual*/, #x /*expected*/) -> ()--  @type checkBetween<#x>-    #x requires Formatted-    #x defines Equals<#x>-    #x defines LessThan<#x>-  (#x /*actual*/, #x /*lower*/, #x /*upper*/) -> ()-}
− tests/helpers.0rx
@@ -1,45 +0,0 @@-/* ------------------------------------------------------------------------------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]--$TestsOnly$--define Testing {-  check (x,y) {-    if (!#x.equals(x,y)) {-      fail(x)-    }-  }--  checkBetween (x,l,h) {-    if (!lessEquals<#x>(l,h)) {-      fail("Invalid range")-    }-    if (!lessEquals<#x>(l,x) || !lessEquals<#x>(x,h)) {-      fail(x)-    }-  }--  @type lessEquals<#x>-    #x defines Equals<#x>-    #x defines LessThan<#x>-  (#x,#x) -> (Bool)-  lessEquals (x,y) {-    // Using !#x.lessThan(y,x) wouldn't account for NaNs.-    return #x.lessThan(x,y) || #x.equals(x,y)-  }-}
tests/inference.0rt view
@@ -17,25 +17,24 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "simple inference" {-  success Test.run()+  success } -define Test {-  run () {-    Int value <- get<?>(10)-  }+unittest test {+  Int value <- Test.get<?>(10)+} +concrete Test {   @type get<#x> (#x) -> (#x)+}++define Test {   get (x) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "inference mismatch" {   error   require "get"@@ -43,26 +42,29 @@   require "Int" } -define Test {-  run () {-    String value <- get<?>(10)-  }+unittest test {+  String value <- Test.get<?>(10)+} +concrete Test {   @type get<#x> (#x) -> (#x)+}++define Test {   get (x) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "nested inference" {-  success Test.run()+  success } +unittest test {+  Type<Int> value <- Test.get<?>(Type<Int>.create())+}+ concrete Type<#x> {   @type create () -> (Type<#x>) }@@ -73,42 +75,36 @@   } } -define Test {-  run () {-    Type<Int> value <- get<?>(Type<Int>.create())-  }-+concrete Test {   @type get<#x> (Type<#x>) -> (Type<#x>)+}++define Test {   get (x) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "simple inference with qualification" {-  success Test.run()+  success } -define Test {-  run () {-    Int value <- Test.get<?>(10)-  }+unittest test {+  Int value <- Test.get<?>(10)+} +concrete Test {   @type get<#x> (#x) -> (#x)+}++define Test {   get (x) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "inference mismatch with qualification" {   error   require "get"@@ -116,26 +112,29 @@   require "Int" } -define Test {-  run () {-    String value <- Test.get<?>(10)-  }+unittest test {+  String value <- Test.get<?>(10)+} +concrete Test {   @type get<#x> (#x) -> (#x)+}++define Test {   get (x) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "nested inference with qualification" {-  success Test.run()+  success } +unittest test {+  Type<Int> value <- Test.get<?>(Type<Int>.create())+}+ concrete Type<#x> {   @type create () -> (Type<#x>) }@@ -146,28 +145,27 @@   } } -define Test {-  run () {-    Type<Int> value <- Test.get<?>(Type<Int>.create())-  }-+concrete Test {   @type get<#x> (Type<#x>) -> (Type<#x>)+}++define Test {   get (x) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "inference conflict" {   error   require "get"   require "#x" } +unittest test {+  Type<Int> value <- Test.get<?>(Type<Int>.create(),"bad")+}+ concrete Type<#x> {   @type create () -> (Type<#x>) }@@ -178,22 +176,17 @@   } } -define Test {-  run () {-    Type<Int> value <- get<?>(Type<Int>.create(),"bad")-  }-+concrete Test {   @type get<#x> (Type<#x>,#x) -> (Type<#x>)+}++define Test {   get (x,_) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "elimination by filter" {   error   require "get"@@ -201,24 +194,23 @@   require "Formatted.+String" } -define Test {-  run () {-    \ get<?>("value")-  }+unittest test {+  \ Test.get<?>("value")+} +concrete Test {   @type get<#x>     #x allows Formatted   (#x) -> (#x)+}++define Test {   get (x) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "elimination by filter without param" {   error   require "get"@@ -226,24 +218,23 @@   require "Formatted.+String" } -define Test {-  run () {-    \ get<Formatted,?>("value")-  }+unittest test {+  \ Test.get<Formatted,?>("value")+} +concrete Test {   @type get<#y,#x>     #x allows #y   (#x) -> (#x)+}++define Test {   get (x) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "elimination by filter including param" {   error   require "get"@@ -252,6 +243,10 @@   require "Type.+String" } +unittest test {+  \ Test.get<?>(Type<String>.create())+}+ concrete Type<#x> {   @type create () -> (Type<#x>) }@@ -262,36 +257,34 @@   } } -define Test {-  run () {-    \ get<?>(Type<String>.create())-  }-+concrete Test {   @type get<#x>     #x allows Type<#x>   (#x) -> (#x)+}++define Test {   get (x) {     return x   } } -concrete Test {-  @type run () -> ()-} - testcase "clashing param filter in the same scope" {-  success Test.run()+  success } -define Test {-  run () {-    \ get1<Int>()-  }+unittest test {+  \ Test.get1<Int>()+} +concrete Test {   @type get1<#x>     #x requires Int   () -> ()+}++define Test {   get1 () {     String value <- get2<?>("message")   }@@ -302,11 +295,7 @@   } } -concrete Test {-  @type run () -> ()-} - testcase "mutually dependent inferences" {   error   require "get"@@ -314,6 +303,12 @@   require "#y.+String" } +unittest test {+    Type<String> x <- Type<String>.create()+    Type<Int>    y <- Type<Int>.create()+    \ Test.get<?,?>(x,y)+}+ concrete Type<#x> {   @type create () -> (Type<#x>) }@@ -324,20 +319,13 @@   } } -define Test {-  run () {-    Type<String> x <- Type<String>.create()-    Type<Int>    y <- Type<Int>.create()-    \ get<?,?>(x,y)-  }-+concrete Test {   @type get<#x,#y>     #x requires Type<#y>     #y requires Type<#x>   (#x,#y) -> ()-  get (_,_) {} } -concrete Test {-  @type run () -> ()+define Test {+  get (_,_) {} }
tests/infix-functions.0rt view
@@ -17,55 +17,60 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "category infix" {-  success Test.run()+  success } -define Test {-  @category add (Int,Int) -> (Int)-  add (x,y) {-    return x + y-  }--  run () {-    Int value <- 1 `Test:add` 2-    if (value != 3) {-      fail(value)-    }+unittest test {+  Int value <- 1 `Test:add` 2+  if (value != 3) {+    fail(value)   } }  concrete Test {-  @type run () -> ()-}---testcase "type infix" {-  success Test.run()+  @category add (Int,Int) -> (Int) }  define Test {-  @type add (Int,Int) -> (Int)   add (x,y) {     return x + y   }+} -  run () {-    Int value <- 1 `Test.add` 2-    if (value != 3) {-      fail(value)-    }++testcase "type infix" {+  success+}++unittest test {+  Int value <- 1 `Test.add` 2+  if (value != 3) {+    fail(value)   } }  concrete Test {-  @type run () -> ()+  @type add (Int,Int) -> (Int) } +define Test {+  add (x,y) {+    return x + y+  }+} + testcase "value infix" {-  success Test.run()+  success } +unittest test {+  Int value <- 1 `Arithmetic.create().add` 2+  if (value != 3) {+    fail(value)+  }+}+ concrete Arithmetic {   @type create () -> (Arithmetic)   @value add (Int,Int) -> (Int)@@ -81,22 +86,13 @@   } } -define Test {-  run () {-    Int value <- 1 `Arithmetic.create().add` 2-    if (value != 3) {-      fail(value)-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "unqualified infix" {+  success } --testcase "unqualified infix" {-  success Test.run()+unittest test {+  \ Test.run() }  define Test {@@ -119,46 +115,44 @@   testcase "infix function comes after arithmetic" {-  success Test.run()+  success } -define Test {-  @category add (Int,Int) -> (Int)-  add (x,y) {-    return x + y-  }--  run () {-    Int value <- 1 `add` 2 * 3-    if (value != 7) {-      fail(value)-    }+unittest test {+  Int value <- 1 `Test:add` 2 * 3+  if (value != 7) {+    fail(value)   } }  concrete Test {-  @type run () -> ()-}---testcase "infix function comes before comparison" {-  success Test.run()+  @category add (Int,Int) -> (Int) }  define Test {-  @category add (Int,Int) -> (Int)   add (x,y) {     return x + y   }+} -  run () {-    Bool value <- 1 `add` 2 < 4-    if (value != true) {-      fail(value)-    }++testcase "infix function comes before comparison" {+  success+}++unittest test {+  Bool value <- 1 `Test:add` 2 < 4+  if (value != true) {+    fail(value)   } }  concrete Test {-  @type run () -> ()+  @category add (Int,Int) -> (Int)+}++define Test {+  add (x,y) {+    return x + y+  } }
tests/infix-operations.0rt view
@@ -16,323 +16,243 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -testcase "Int arithmetic with precedence" {-  success Test.run()+testcase "Int operations" {+  success } -define Test {-  run () {-    \ Testing.check<?>(\x10 + 1 * 2 - 8 / 2 - 3 % 2,13)-  }+unittest plus {+  \ Testing.checkEquals<?>(8 + 2,10) } -concrete Test {-  @type run () -> ()+unittest minus {+  \ Testing.checkEquals<?>(8 - 2,6) } --testcase "Int arithmetic" {-  success Test.run()+unittest times {+  \ Testing.checkEquals<?>(8 * 2,16) } -define Test {-  run () {-    \ Testing.check<?>(8 + 2,10)-    \ Testing.check<?>(8 - 2,6)-    \ Testing.check<?>(8 * 2,16)-    \ Testing.check<?>(8 / 2,4)-    \ Testing.check<?>(8 % 2,0)-  }+unittest divide {+  \ Testing.checkEquals<?>(8 / 2,4) } -concrete Test {-  @type run () -> ()+unittest modulo {+  \ Testing.checkEquals<?>(8 % 2,0) } --testcase "Int bitwise" {-  success Test.run()+unittest left {+  \ Testing.checkEquals<?>(1 << 2,4) } -define Test {-  run () {-    \ Testing.check<?>(1 << 2,4)-    \ Testing.check<?>(7 >> 1,3)-    \ Testing.check<?>(7 ^ 2 ,5)-    \ Testing.check<?>(7 & ~2,5)-    \ Testing.check<?>(5 | 2 ,7)-  }+unittest right {+  \ Testing.checkEquals<?>(7 >> 1,3) } -concrete Test {-  @type run () -> ()+unittest xor {+  \ Testing.checkEquals<?>(7 ^ 2 ,5) } --testcase "Int bitwise with precedence" {-  success Test.run()+unittest and {+  \ Testing.checkEquals<?>(7 & ~2,5) } -define Test {-  run () {-    \ Testing.check<?>(1 << 4 | 7 >> 1 & ~2,17)-  }+unittest or {+  \ Testing.checkEquals<?>(5 | 2 ,7) } -concrete Test {-  @type run () -> ()+unittest arithmetic {+  \ Testing.checkEquals<?>(\x10 + 1 * 2 - 8 / 2 - 3 % 2,13) } --testcase "same operators applied left to right" {-  success Test.run()+unittest bitwise {+  \ Testing.checkEquals<?>(1 << 4 | 7 >> 1 & ~2,17) } -define Test {-  run () {-    \ Testing.check<?>(2 - 1 - 1,0)-  }+unittest sameOperator {+  \ Testing.checkEquals<?>(2 - 1 - 1,0) } -concrete Test {-  @type run () -> ()+unittest lessThan {+  if (!(1 <  2)) { fail("Failed") } } --testcase "Int + Bool" {-  error-  require "Int.+Bool"+unittest lessEquals {+  if (!(1 <= 2)) { fail("Failed") } } -define Test {-  run () {-    \ \x10 + false-  }+unittest equals {+  if (!(1 == 1)) { fail("Failed") } } -concrete Test {-  @type run () -> ()+unittest notEquals {+  if (!(1 != 2)) { fail("Failed") } } --testcase "Int + String" {-  error-  require "Int.+String"+unittest greaterThan {+  if (!(2 >  1)) { fail("Failed") } } -define Test {-  run () {-    \ \x10 + ""-  }+unittest greaterEquals {+  if (!(2 >= 1)) { fail("Failed") } } -concrete Test {-  @type run () -> ()+unittest arithmeticCompare {+  if (!(2 + 1 < 2 + 3)) { fail("Failed") } }  -testcase "String arithmetic" {-  success Test.run()+testcase "Bool operations" {+  success } -define Test {-  run () {-    \ Testing.check<?>("x" + "y" + "z","xyz")+unittest precedence {+  scoped {+    Bool x <- false && false || true+  } in if (!x) {+    fail(x)   } } -concrete Test {-  @type run () -> ()+unittest trueEqualsTrue {+  if (!(true  == true))  { fail("Failed") } } --testcase "Float arithmetic with precedence" {-  success Test.run()+unittest falseEqualsFalse {+  if (!(false == false)) { fail("Failed") } } -define Test {-  run () {-    \ Testing.check<?>(16.0 + 1.0 * 2.0 - 8.0 / 2.0 - 3.0 / 3.0,13.0)-  }+unittest falseNotEqualsTrue {+  if (!(false != true))  { fail("Failed") } } -concrete Test {-  @type run () -> ()+unittest compareWithLogic {+  scoped {+    Bool x <- 1 + 2 < 4 && 3 >= 1 * 2 + 1+  } in if (!x) {+    fail(x)+  } }  -testcase "Char minus" {-  success Test.run()+testcase "Float operations" {+  success } -define Test {-  run () {-    \ Testing.check<?>('z' - 'a',25)-  }+unittest precedence {+  \ Testing.checkEquals<?>(16.0 + 1.0 * 2.0 - 8.0 / 2.0 - 3.0 / 3.0,13.0) } -concrete Test {-  @type run () -> ()+unittest lessThan {+  if (!(1.0 <  2.0)) { fail("Failed") } } --testcase "Bool comparison" {-  success Test.run()+unittest lessEquals {+  if (!(1.0 <= 2.0)) { fail("Failed") } } -define Test {-  run () {-    if (!(true  == true))  { fail("Failed") }-    if (!(false == false)) { fail("Failed") }-    if (!(false != true))  { fail("Failed") }-  }+unittest equals {+  if (!(1.0 == 1.0)) { fail("Failed") } } -concrete Test {-  @type run () -> ()+unittest notEquals {+  if (!(1.0 != 2.0)) { fail("Failed") } } --testcase "Int comparison" {-  success Test.run()+unittest greaterThan {+  if (!(2.0 >  1.0)) { fail("Failed") } } -define Test {-  run () {-    if (!(1 <  2)) { fail("Failed") }-    if (!(1 <= 2)) { fail("Failed") }-    if (!(1 == 1)) { fail("Failed") }-    if (!(1 != 2)) { fail("Failed") }-    if (!(2 >  1)) { fail("Failed") }-    if (!(2 >= 1)) { fail("Failed") }-  }+unittest greaterEquals {+  if (!(2.0 >= 1.0)) { fail("Failed") } } -concrete Test {-  @type run () -> ()+unittest arithmeticCompare {+  if (!(2.0 + 1.0 < 2.0 + 3.0)) { fail("Failed") } }  -testcase "Float comparison" {-  success Test.run()+testcase "String operations" {+  success } -define Test {-  run () {-    if (!(1.0 <  2.0)) { fail("Failed") }-    if (!(1.0 <= 2.0)) { fail("Failed") }-    if (!(1.0 == 1.0)) { fail("Failed") }-    if (!(1.0 != 2.0)) { fail("Failed") }-    if (!(2.0 >  1.0)) { fail("Failed") }-    if (!(2.0 >= 1.0)) { fail("Failed") }-  }+unittest add {+  \ Testing.checkEquals<?>("x" + "y" + "z","xyz") } -concrete Test {-  @type run () -> ()+unittest lessThan {+  if (!("x" <  "y")) { fail("Failed") } } --testcase "String comparison" {-  success Test.run()+unittest lessEquals {+  if (!("x" <= "y")) { fail("Failed") } } -define Test {-  run () {-    if (!("x" <  "y")) { fail("Failed") }-    if (!("x" <= "y")) { fail("Failed") }-    if (!("x" == "x")) { fail("Failed") }-    if (!("x" != "y")) { fail("Failed") }-    if (!("y" >  "x")) { fail("Failed") }-    if (!("y" >= "x")) { fail("Failed") }-  }+unittest equals {+  if (!("x" == "x")) { fail("Failed") } } -concrete Test {-  @type run () -> ()+unittest notEquals {+  if (!("x" != "y")) { fail("Failed") } } --testcase "Char comparison" {-  success Test.run()+unittest greaterThan {+  if (!("y" >  "x")) { fail("Failed") } } -define Test {-  run () {-    if (!('x' <  'y')) { fail("Failed") }-    if (!('x' <= 'y')) { fail("Failed") }-    if (!('x' == 'x')) { fail("Failed") }-    if (!('x' != 'y')) { fail("Failed") }-    if (!('y' >  'x')) { fail("Failed") }-    if (!('y' >= 'x')) { fail("Failed") }-  }+unittest greaterEquals {+  if (!("y" >= "x")) { fail("Failed") } } -concrete Test {-  @type run () -> ()+unittest arithmeticCompare {+  if (!("x" + "w" < "x" + "y")) { fail("Failed") } }  -testcase "Bool logic with precedence" {-  success Test.run()+testcase "Char operations" {+  success } -define Test {-  run () {-    scoped {-      Bool x <- false && false || true-    } in if (!x) {-      fail(x)-    }-  }+unittest minus {+  \ Testing.checkEquals<?>('z' - 'a',25) } -concrete Test {-  @type run () -> ()+unittest lessThan {+  if (!('x' <  'y')) { fail("Failed") } } --testcase "minus String" {-  error-  require "String.+String"+unittest lessEquals {+  if (!('x' <= 'y')) { fail("Failed") } } -define Test {-  run () {-    \ "x" - "x"-  }+unittest equals {+  if (!('x' == 'x')) { fail("Failed") } } -concrete Test {-  @type run () -> ()+unittest notEquals {+  if (!('x' != 'y')) { fail("Failed") } } --testcase "arithmetic Bool" {-  error-  require "Bool.+Bool"+unittest greaterThan {+  if (!('y' >  'x')) { fail("Failed") } } -define Test {-  run () {-    \ true - false-  }+unittest greaterEquals {+  if (!('y' >= 'x')) { fail("Failed") } } -concrete Test {-  @type run () -> ()+unittest arithmeticCompare {+  if (!('d' - 'a' == 3)) { fail("Failed") } }  -testcase "String plus with comparison" {-  success Test.run()+testcase "Int + Bool" {+  error+  require "Int.+Bool" }  define Test {   run () {-    if (!("x" + "w" < "x" + "y")) {-      fail("Failed")-    }+    \ \x10 + false   } } @@ -341,15 +261,14 @@ }  -testcase "Char minus with comparison" {-  success Test.run()+testcase "Int + String" {+  error+  require "Int.+String" }  define Test {   run () {-    if (!('d' - 'a' == 3)) {-      fail("Failed")-    }+    \ \x10 + ""   } } @@ -358,15 +277,14 @@ }  -testcase "Int arithmetic with comparison" {-  success Test.run()+testcase "minus String" {+  error+  require "String.+String" }  define Test {   run () {-    if (!(2 + 1 < 2 + 3)) {-      fail("Failed")-    }+    \ "x" - "x"   } } @@ -375,15 +293,14 @@ }  -testcase "Float arithmetic with comparison" {-  success Test.run()+testcase "arithmetic Bool" {+  error+  require "Bool.+Bool" }  define Test {   run () {-    if (!(2.0 + 1.0 < 2.0 + 3.0)) {-      fail("Failed")-    }+    \ true - false   } } @@ -400,25 +317,6 @@ define Test {   run () {     \ 1 < 2 < 3-  }-}--concrete Test {-  @type run () -> ()-}---testcase "arithmetic, comparison, logic" {-  success Test.run()-}--define Test {-  run () {-    scoped {-      Bool x <- 1 + 2 < 4 && 3 >= 1 * 2 + 1-    } in if (!x) {-      fail(x)-    }   } } 
tests/internal-inheritance.0rt view
@@ -32,9 +32,16 @@   testcase "internal refine is private" {-  success Test.run()+  success } +unittest test {+  String value <- Value.create().get().formatted()+  if (value != "Value") {+    fail(value)+  }+}+ concrete Value {   @type create () -> (Value)   @value get () -> (Formatted)@@ -56,20 +63,7 @@   } } -define Test {-  run () {-    String value <- Value.create().get().formatted()-    if (value != "Value") {-      fail(value)-    }-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "internal refine is not public" {   error   require "refine"@@ -77,6 +71,10 @@   require "Value" } +unittest test {+  Formatted value <- Value.create()+}+ concrete Value {   @type create () -> (Value) }@@ -93,19 +91,17 @@   } } -define Test {-  run () {-    Formatted value <- Value.create()-  }-} -concrete Test {-  @type run () -> ()+testcase "internal define is private" {+  success } --testcase "internal define is private" {-  success Test.run()+unittest test {+  Value value1 <- Value.create(1)+  Value value2 <- Value.create(2)+  if (Value.compare(value1,value2)) {+    fail("Failed")+  } }  concrete Compare<#x> {@@ -148,21 +144,7 @@   } } -define Test {-  run () {-    Value value1 <- Value.create(1)-    Value value2 <- Value.create(2)-    if (Value.compare(value1,value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "internal define is not public" {   error   require "define"@@ -170,6 +152,12 @@   require "Value" } +unittest test {+  Value value1 <- Value.create(1)+  Value value2 <- Value.create(2)+  \ Compare<Value>.compare(value1,value2)+}+ concrete Compare<#x> {   #x defines Equals<#x> @@ -203,18 +191,4 @@   get () {     return value   }-}--define Test {-  run () {-    Value value1 <- Value.create(1)-    Value value2 <- Value.create(2)-    if (Compare<Value>.compare(value1,value2)) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> () }
tests/internal-params.0rt view
@@ -32,17 +32,13 @@   } } -define Test {-  run () {}-} -concrete Test {-  @type run () -> ()+testcase "internal filter not applied in @type" {+  compiles } --testcase "internal filter not applied in @type" {-  success Test.run()+unittest test {+  \ Value.something<Bool>() }  concrete Value {@@ -57,19 +53,13 @@   something () {} } -define Test {-  run () {-    \ Value.something<Bool>()-  }-} -concrete Test {-  @type run () -> ()+testcase "internal filter not applied in @category" {+  compiles } --testcase "internal filter not applied in @category" {-  success Test.run()+unittest test {+  \ Value:something<Bool>() }  concrete Value {@@ -84,19 +74,13 @@   something () {} } -define Test {-  run () {-    \ Value:something<Bool>()-  }-} -concrete Test {-  @type run () -> ()+testcase "internal params" {+  success } --testcase "internal params" {-  success Test.run()+unittest test {+  \ Value.create<Type1,Type2>() }  concrete Value {@@ -115,19 +99,9 @@ @value interface Type1 {} @value interface Type2 {} -define Test {-  run () {-    \ Value.create<Type1,Type2>()-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "internal params with filters" {-  success Test.run()+  compiles }  @value interface Get<|#x> {@@ -156,15 +130,7 @@   } } -define Test {-  run () {}-} -concrete Test {-  @type run () -> ()-}-- testcase "internal params missing filters" {   error   require "Get|Set"@@ -194,17 +160,9 @@   } } -define Test {-  run () {}-} -concrete Test {-  @type run () -> ()-}-- testcase "internal params with values" {-  success Test.run()+  compiles }  concrete Value {@@ -222,17 +180,13 @@   } } -define Test {-  run () {}-} -concrete Test {-  @type run () -> ()+testcase "value depends on internal param" {+  success } --testcase "value depends on internal param" {-  success Test.run()+unittest test {+  \ Value.create<Bool>(Type<Bool>.create()) }  concrete Type<#y> {@@ -241,7 +195,7 @@  define Type {   create () {-    return Type<#y>{}+    return Type<#y>{ }   } } @@ -260,17 +214,7 @@   } } -define Test {-  run () {-    \ Value.create<Bool>(Type<Bool>.create())-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "value mismatch with internal param" {   error   require "create"@@ -278,13 +222,17 @@   require "String" } +unittest test {+  \ Value.create<String>(Type<Bool>.create())+}+ concrete Type<#y> {   @type create () -> (Type<#y>) }  define Type {   create () {-    return Type<#y>{}+    return Type<#y>{ }   } } @@ -303,17 +251,7 @@   } } -define Test {-  run () {-    \ Value.create<String>(Type<Bool>.create())-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "internal param clash with external" {   error   require "#x"@@ -325,15 +263,7 @@   types<#x> {} } -define Test {-  run () {}-} -concrete Test {-  @type run () -> ()-}-- testcase "internal param clash with function" {   error   require "#x"@@ -347,15 +277,7 @@   types<#x> {} } -define Test {-  run () {}-} -concrete Test {-  @type run () -> ()-}-- testcase "internal param clash with internal function" {   error   require "#x"@@ -370,17 +292,9 @@   check () {} } -define Test {-  run () {}-} -concrete Test {-  @type run () -> ()-}-- testcase "internal param no clash with category" {-  success Test.run()+  compiles }  concrete Value {@@ -395,17 +309,16 @@   } } -define Test {-  run () {}-} -concrete Test {-  @type run () -> ()+testcase "reduce internal param success" {+  success } --testcase "reduce internal param success" {-  success Test.run()+unittest test {+  Value value <- Value.create<Formatted>()+  if (!value.check<String>("")) {+    fail("Failed")+  } }  concrete Value {@@ -425,22 +338,16 @@   } } -define Test {-  run () {-    Value value <- Value.create<Formatted>()-    if (!value.check<String>("")) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce internal param fail" {+  success } --testcase "reduce internal param fail" {-  success Test.run()+unittest test {+  Value value <- Value.create<Formatted>()+  if (value.check<Value>(value)) {+    fail("Failed")+  } }  concrete Value {@@ -458,17 +365,4 @@   check (y) {     return present(reduce<#y,#x>(y))   }-}--define Test {-  run () {-    Value value <- Value.create<Formatted>()-    if (value.check<Value>(value)) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> () }
tests/member-init.0rt view
@@ -23,19 +23,21 @@  define Test {   @type Bool value <- false--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Test {}   testcase "@category member from @type" {-  success Test.run()+  success } +unittest test {+  // NOTE: Executing the test ensures that C++ compilation works.+}++concrete Test {}+ define Test {   @category Bool value <- true @@ -43,19 +45,19 @@   call () {     \ value   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "@category member from @value" {-  success Test.run()+  success } +unittest test {+  // NOTE: Executing the test ensures that C++ compilation works.+}++concrete Test {}+ define Test {   @category Bool value <- true @@ -63,20 +65,16 @@   call () {     \ value   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "@category to @category" {   error   require "get" } +concrete Test {}+ define Test {   @category Bool value <- get() @@ -84,42 +82,40 @@   get () {     return true   }--  run () {} } -concrete Test {-  @type run () -> ()++testcase "@category member refers to @category member" {+  success } +unittest test {+  \ Testing.checkEquals<?>(Test:get(),2)+} -testcase "@category member refers to @category member" {-  success Test.run()+concrete Test {+  @category get () -> (Int) }  define Test {   @category Int value1 <- 1   @category Int value2 <- value1+1 -  @category get () -> (Int)   get () {     return value2   }--  run () {-    \ Testing.check<?>(get(),2)-  } } -concrete Test {-  @type run () -> ()-} - testcase "@category member is lazy" {-  success Test.run()+  success } +unittest test {+  // Constructing Test ensures that the instance is actually created.+  \ typename<Test>()+}+ concrete Util {   @type doNotUse () -> (Bool) }@@ -130,22 +126,22 @@   } } +concrete Test {}+ define Test {   @category Bool value <- Util.doNotUse()--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "@category member init when read" {-  crash Test.run()+  crash   require "do not use" } +unittest test {+  \ Test.run()+}+ concrete Util {   @type doNotUse () -> (Bool) }@@ -156,6 +152,10 @@   } } +concrete Test {+  @type run () -> ()+}+ define Test {   @category Bool value <- Util.doNotUse() @@ -164,16 +164,16 @@   } } -concrete Test {-  @type run () -> ()-} - testcase "@category member init when assigned" {-  crash Test.run()+  crash   require "do not use" } +unittest test {+  \ Test.run()+}+ concrete Util {   @type doNotUse () -> (Bool) }@@ -184,6 +184,10 @@   } } +concrete Test {+  @type run () -> ()+}+ define Test {   @category Bool value <- Util.doNotUse() @@ -192,16 +196,16 @@   } } -concrete Test {-  @type run () -> ()-} - testcase "@category member init when ignored" {-  crash Test.run()+  crash   require "do not use" } +unittest test {+  \ Test.run()+}+ concrete Util {   @type doNotUse () -> (Bool) }@@ -212,6 +216,10 @@   } } +concrete Test {+  @type run () -> ()+}+ define Test {   @category Bool value <- Util.doNotUse() @@ -220,13 +228,17 @@   } } -concrete Test {-  @type run () -> ()++testcase "@category member inline assignment" {+  success } +unittest test {+  \ Test.run()+} -testcase "@category member inline assignment" {-  success Test.run()+concrete Test {+  @type run () -> () }  define Test {@@ -238,22 +250,22 @@   }    run () {-    if (call() || value) {+    if (Test.call() || value) {       fail("Failed")     }   } } -concrete Test {-  @type run () -> ()-} - testcase "@category init cycle" {-  crash Test.run()+  crash   require "Value1|Value2" } +unittest test {+  \ Value1.get()+}+ concrete Value1 {   @type get () -> (Bool) }@@ -278,38 +290,26 @@   } } -define Test {-  run () {-    \ Value1.get()-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "self in @category init" {   error   require "self" } +concrete Test {}+ define Test {   @category Test value <- self--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "cycle in @category init" {   error   require "disallowed" } +concrete Test {}+ define Test {   @category Bool value <- get() @@ -317,10 +317,4 @@   get () {     return value   }--  run () {}-}--concrete Test {-  @type run () -> () }
tests/modified-storage.0rt view
@@ -17,61 +17,69 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "optional persists" {-  success Test.run()+  success } +unittest test {+  Test value <- Test.create()+  \ value.set()+  \ value.check()+}++concrete Test {+  @type create () -> (Test)+  @value set () -> ()+  @value check () -> ()+}+ define Test {   @value optional Test self2 -  @type create () -> (Test)   create () {     return Test{ empty }   } -  @value set () -> ()   set () {     scoped {       Test value <- create()     } in self2 <- value   } -  @value check () -> ()   check () {     \ require(self2)   }--  run () {-    Test value <- create()-    \ value.set()-    \ value.check()-  } } -concrete Test {-  @type run () -> ()++testcase "weak is weak" {+  success } +unittest test {+  Test value <- Test.create()+  \ value.set()+  \ value.check()+} -testcase "weak is weak" {-  success Test.run()+concrete Test {+  @type create () -> (Test)+  @value set () -> ()+  @value check () -> () }  define Test {   @value weak Test self2 -  @type create () -> (Test)   create () {     return Test{ empty }   } -  @value set () -> ()   set () {     scoped {       Test value <- create()     } in self2 <- value   } -  @value check () -> ()   check () {     scoped {       optional Test self3 <- strong(self2)@@ -79,52 +87,45 @@       fail("Failed")     }   }--  run () {-    Test value <- create()-    \ value.set()-    \ value.check()-  } } -concrete Test {-  @type run () -> ()++testcase "present weak" {+  success } +unittest test {+  Test value <- Test.create()+  \ value.check()+} -testcase "present weak" {-  success Test.run()+concrete Test {+  @type create () -> (Test)+  @value check () -> () }  define Test {-  @type create () -> (Test)   create () {-    return Test{}+    return Test{ }   } -  @value check () -> ()   check () {     weak Test value <- create()     if (present(strong(value))) {  // value should be nullptr here       fail("Failed")     }   }--  run () {-    Test value <- create()-    \ value.check()-  } } -concrete Test {-  @type run () -> ()-} - testcase "weak variable to weak variable" {-  success Test.run()+  success } +unittest test {+  \ Test.run()+}+ define Test {   @category weak Test one <- empty @@ -140,9 +141,13 @@   testcase "optional variable to weak variable" {-  success Test.run()+  success } +unittest test {+  \ Test.run()+}+ define Test {   @category optional Test one <- empty @@ -158,111 +163,102 @@   testcase "weak in multi assign" {-  success Test.run()+  success } +unittest test {+  // value1 ensures value2 is present.+  Value value1, weak Value value2 <- Test.get()+  if (!present(strong(value2))) {+    fail("Failed")+  }+}+ concrete Value {   @type create () -> (Value) }  define Value {   create () {-    return Value{}+    return Value{ }   } } -define Test {+concrete Test {   @type get () -> (Value,Value)+}++define Test {   get () {     Value value <- Value.create()     return value, value   }--  run () {-    // value1 ensures value2 is present.-    Value value1, weak Value value2 <- get()-    if (!present(strong(value2))) {-      fail("Failed")-    }-  } } -concrete Test {-  @type run () -> ()-} - testcase "weak in inline assign" {-  success Test.run()+  success } +unittest test {+  Value value1 <- Value.create()+  weak Value value2 <- empty+  if (!present(strong((value2 <- value1)))) {+    fail("Failed")+  }+}+ concrete Value {   @type create () -> (Value) }  define Value {   create () {-    return Value{}+    return Value{ }   } } -define Test {-  run () {-    Value value1 <- Value.create()-    weak Value value2 <- empty-    if (!present(strong((value2 <- value1)))) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "present required" {+  success } +unittest test {+  Test value <- Test.create()+  if (!present(value)) {+    fail("Failed")+  }+} -testcase "present required" {-  success Test.run()+concrete Test {+  @type create () -> (Test) }  define Test {-  @type create () -> (Test)   create () {-    return Test{}-  }--  run () {-    Test value <- create()-    if (!present(value)) {-      fail("Failed")-    }+    return Test{ }   } } -concrete Test {-  @type run () -> ()++testcase "require required" {+  success } +unittest test {+  Test value <- Test.create()+  \ require(value).call()+} -testcase "require required" {-  success Test.run()+concrete Test {+  @type create () -> (Test)+  @value call () -> () }  define Test {-  @type create () -> (Test)   create () {-    return Test{}+    return Test{ }   } -  @value call () -> ()   call () {}--  run () {-    Test value <- create()-    \ require(value).call()-  }-}--concrete Test {-  @type run () -> () }
tests/multiple-returns.0rt view
@@ -31,13 +31,9 @@   process (value) {     \ value.get().call()   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Test {}   testcase "zero return to call" {@@ -55,53 +51,50 @@   process (value) {     \ value.get().call()   }--  run () {} } -concrete Test {-  @type run () -> ()-}+concrete Test {}   testcase "multi return assign" {-  success Test.run()+  success } -define Test {+unittest test {+  Test value <- Test.create()+  _, Test value2 <- value.double()+  value, _ <- value2.double()+}++concrete Test {   @type create () -> (Test)+  @value double () -> (Test,Test)+}++define Test {   create () {     return Test{}   } -  @value double () -> (Test,Test)   double () {     return self, self   }--  run () {-    Test value <- create()-    _, Test value2 <- value.double()-    value, _ <- value2.double()-  } } -concrete Test {-  @type run () -> ()-} - testcase "multi return as args" {-  success Test.run()+  success } +unittest test {+    \ Test.call(Test.get())+}+ define Test {-  @type get () -> (Int,Int)   get () {     return 1, 2   } -  @type call (Int,Int) -> ()   call (x,y) {     if (x != 1) {       fail("Failed")@@ -110,12 +103,9 @@       fail("Failed")     }   }--  run () {-    \ call(get())-  } }  concrete Test {-  @type run () -> ()+  @type get () -> (Int,Int)+  @type call (Int,Int) -> () }
tests/named-returns.0rt view
@@ -23,264 +23,231 @@  @value interface Value {} +concrete Test {}+ define Test {   @value process () -> (Value)   process () (value) {}--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "assign before logical" {-  success Test.run()+  compiles } +concrete Test {}+ define Test {   @value process () -> (Bool)   process () (value) {     \ (value <- true) || false   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "assign after logical" {   error   require "value" } +concrete Test {}+ define Test {   @value process () -> (Bool)   process () (value) {     \ false || (value <- true)   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "assign before arithmetic" {-  success Test.run()+  compiles } +concrete Test {}+ define Test {   @value process () -> (Int)   process () (value) {     \ (value <- 1) + 2   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "assign after arithmetic" {-  success Test.run()+  compiles } +concrete Test {}+ define Test {   @value process () -> (Int)   process () (value) {     \ 2 + (value <- 1)   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "return used before assigned" {   error   require "value.+initialized" } +concrete Test {}+ define Test {   @category process () -> (Int)   process () (value) {     value <- value+1   }--  run () {} } -concrete Test {-  @type run () -> ()++testcase "return used after assigned" {+  success } +unittest test {+  Int value <- Test:process()+  if (value != 2) {+    fail("Failed")+  }+} -testcase "return used after assigned" {-  success Test.run()+concrete Test {+  @category process () -> (Int) }  define Test {-  @category process () -> (Int)   process () (value) {     value <- 1     value <- value+1   }--  run () {-    Int value <- process()-    if (value != 2) {-      fail("Failed")-    }-  } } -concrete Test {-  @type run () -> ()-} - testcase "return used as return before assigned" {   error   require "value.+initialized" } +concrete Test {}+ define Test {   @category process () -> (Int)   process () (value) {     return value   }--  run () {} } -concrete Test {-  @type run () -> ()++testcase "returns in correct order" {+  success } +unittest test {+  scoped {+    Int x, Int y <- Test.get()+  } in if (x != 1) {+    fail("Failed")+  } elif (y != 2) {+    fail("Failed")+  }+} -testcase "returns in correct order" {-  success Test.run()+concrete Test {+  @type get () -> (Int,Int) }  define Test {-  @type get () -> (Int,Int)   get () {     return 1, 2   }--  run () {-    scoped {-      Int x, Int y <- get()-    } in if (x != 1) {-      fail("Failed")-    } elif (y != 2) {-      fail("Failed")-    }-  } } -concrete Test {-  @type run () -> ()-} - testcase "assigns in correct order" {-  success Test.run()+  success } +unittest test {+  scoped {+    _, Int x, Int y <- Test.get()+  } in if (x != 1) {+    fail("Failed")+  } elif (y != 2) {+    fail("Failed")+  }+}+ concrete Value {   @type create () -> (Value) }  define Value {   create () {-    return Value{}+    return Value{ }   } } -define Test {+concrete Test {   @type get () -> (Value,Int,Int)+}++define Test {   get () (v,x,y) {     // This makes sure that x and y (primitive) are offset.     v <- Value.create()     x <- 1     y <- 2   }--  run () {-    scoped {-      _, Int x, Int y <- get()-    } in if (x != 1) {-      fail("Failed")-    } elif (y != 2) {-      fail("Failed")-    }-  } } -concrete Test {-  @type run () -> ()++testcase "assigns in correct order with explicit return" {+  success } +unittest test {+  scoped {+    Int x, Int y <- Test.get()+  } in if (x != 1) {+    fail("Failed")+  } elif (y != 2) {+    fail("Failed")+  }+} -testcase "assigns in correct order with explicit return" {-  success Test.run()+concrete Test {+  @type get () -> (Int,Int) }  define Test {-  @type get () -> (Int,Int)   get () (x,y) {     x <- 1     y <- 2     return _   }--  run () {-    scoped {-      Int x, Int y <- get()-    } in if (x != 1) {-      fail("Failed")-    } elif (y != 2) {-      fail("Failed")-    }-  } } -concrete Test {-  @type run () -> ()-} - testcase "positional return sets named return" {-  crash Test.run()+  crash   require "message" } -define Test {+unittest test {+  \ Test.get()+}++concrete Test {   @type get () -> (String)+}++define Test {   get () (value) {     cleanup {       fail(value)     } in return "message"   }--  run () {-    \ get()-  }-}--concrete Test {-  @type run () -> () }
tests/positional-returns.0rt view
@@ -23,24 +23,33 @@  @value interface Value {} +concrete Test {}+ define Test {   @value process () -> (Value)   process () {}--  run () {} } -concrete Test {-  @type run () -> ()++testcase "positional return with no names assigned" {+  success } +unittest test {+  scoped {+    Int x, Int y <- Test.get()+  } in if (x != 3) {+    fail("Failed")+  } elif (y != 4) {+    fail("Failed")+  }+} -testcase "positional return with no names assigned" {-  success Test.run()+concrete Test {+  @type get () -> (Int,Int) }  define Test {-  @type get () -> (Int,Int)   get () (x,y) {     if (false) {       x <- 1@@ -49,55 +58,53 @@     }     y <- 2   }--  run () {-    scoped {-      Int x, Int y <- get()-    } in if (x != 3) {-      fail("Failed")-    } elif (y != 4) {-      fail("Failed")-    }-  } } -concrete Test {-  @type run () -> ()++testcase "positional return instead of names" {+  success } +unittest test {+  scoped {+    Int x, Int y <- Test.get()+  } in if (x != 1) {+    fail("Failed")+  } elif (y != 2) {+    fail("Failed")+  }+} -testcase "positional return instead of names" {-  success Test.run()+concrete Test {+  @type get () -> (Int,Int) }  define Test {-  @type get () -> (Int,Int)   get () (x,y) {     return 1, 2   }--  run () {-    scoped {-      Int x, Int y <- get()-    } in if (x != 1) {-      fail("Failed")-    } elif (y != 2) {-      fail("Failed")-    }-  } } -concrete Test {-  @type run () -> ()++testcase "positional return with some names assigned" {+  success } +unittest test {+  scoped {+    Int x, Int y <- Test.get()+  } in if (x != 3) {+    fail("Failed")+  } elif (y != 4) {+    fail("Failed")+  }+} -testcase "positional return with some names assigned" {-  success Test.run()+concrete Test {+  @type get () -> (Int,Int) }  define Test {-  @type get () -> (Int,Int)   get () (x,y) {     y <- 2     if (false) {@@ -106,18 +113,4 @@       return 3, 4     }   }--  run () {-    scoped {-      Int x, Int y <- get()-    } in if (x != 3) {-      fail("Failed")-    } elif (y != 4) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> () }
tests/reduce.0rt view
@@ -17,9 +17,18 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "reduce to self" {-  success Test.run()+  success } +unittest test {+  Value value <- Value.create()+  scoped {+    optional Value value2 <- reduce<Value,Value>(value)+  } in if (!present(value2)) {+    fail("Failed")+  }+}+ concrete Value {   @type create () -> (Value) }@@ -30,24 +39,18 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    scoped {-      optional Value value2 <- reduce<Value,Value>(value)-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce to unrelated" {+  success } --testcase "reduce to unrelated" {-  success Test.run()+unittest test {+  Value value <- Value.create()+  scoped {+    optional String value2 <- reduce<Value,String>(value)+  } in if (present(value2)) {+    fail("Failed")+  } }  concrete Value {@@ -60,27 +63,19 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    scoped {-      optional Test value2 <- reduce<Value,Test>(value)-    } in if (present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "reduce wrong arg type" {   error-  require "argument"+  require "String"+  require "Value"+  exclude "value2" } +unittest test {+  Value value <- Value.create()+  optional Value value2 <- reduce<String,Value>(value)+}+ concrete Value {   @type create () -> (Value) }@@ -91,23 +86,19 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    optional Value value2 <- reduce<Test,Value>(value)-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "reduce wrong return type" {   error-  require "assignment"+  require "String"+  require "Value"+  require "value2" } +unittest test {+  Value value <- Value.create()+  optional Value value2 <- reduce<Value,String>(value)+}+ concrete Value {   @type create () -> (Value) }@@ -118,20 +109,18 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    optional Value value2 <- reduce<Value,Test>(value)-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce success with param" {+  success } --testcase "reduce success with param" {-  success Test.run()+unittest test {+  Value<Type2> value <- Value<Type2>.create()+  scoped {+    optional Value<Type1> value2 <- value.attempt<Type1>()+  } in if (!present(value2)) {+    fail("Failed")+  } }  concrete Value<|#x> {@@ -157,24 +146,18 @@   refines Type1 } -define Test {-  run () {-    Value<Type2> value <- Value<Type2>.create()-    scoped {-      optional Value<Type1> value2 <- value.attempt<Type1>()-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce fail with param" {+  success } --testcase "reduce fail with param" {-  success Test.run()+unittest test {+  Value<Type1> value <- Value<Type1>.create()+  scoped {+    optional Value<Type2> value2 <- value.attempt<Type2>()+  } in if (present(value2)) {+    fail("Failed")+  } }  concrete Value<|#x> {@@ -200,24 +183,18 @@   refines Type1 } -define Test {-  run () {-    Value<Type1> value <- Value<Type1>.create()-    scoped {-      optional Value<Type2> value2 <- value.attempt<Type2>()-    } in if (present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce success with contra param" {+  success } --testcase "reduce success with contra param" {-  success Test.run()+unittest test {+  Value<Value<Type2>> value <- Value<Value<Type2>>.create()+  scoped {+    optional Value<Value<Type1>> value2 <- value.attempt<Value<Type1>>()+  } in if (!present(value2)) {+    fail("Failed")+  } }  concrete Value<#x|> {@@ -243,24 +220,18 @@   refines Type1 } -define Test {-  run () {-    Value<Value<Type2>> value <- Value<Value<Type2>>.create()-    scoped {-      optional Value<Value<Type1>> value2 <- value.attempt<Value<Type1>>()-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce fail with contra param" {+  success } --testcase "reduce fail with contra param" {-  success Test.run()+unittest test {+  Value<Value<Type1>> value <- Value<Value<Type1>>.create()+  scoped {+    optional Value<Value<Type2>> value2 <- value.attempt<Value<Type2>>()+  } in if (present(value2)) {+    fail("Failed")+  } }  concrete Value<#x|> {@@ -286,24 +257,18 @@   refines Type1 } -define Test {-  run () {-    Value<Value<Type1>> value <- Value<Value<Type1>>.create()-    scoped {-      optional Value<Value<Type2>> value2 <- value.attempt<Value<Type2>>()-    } in if (present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce success from union" {+  success } --testcase "reduce success from union" {-  success Test.run()+unittest test {+  [Value1|Value2] value <- Value1.create()+  scoped {+    optional Base value2 <- reduce<[Value1|Value2],Base>(value)+  } in if (!present(value2)) {+    fail("Failed")+  } }  @value interface Base {}@@ -324,24 +289,18 @@   refines Base } -define Test {-  run () {-    [Value1|Value2] value <- Value1.create()-    scoped {-      optional Base value2 <- reduce<[Value1|Value2],Base>(value)-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce fail from union" {+  success } --testcase "reduce fail from union" {-  success Test.run()+unittest test {+  [Value1|Value2] value <- Value1.create()+  scoped {+    optional Value2 value2 <- reduce<[Value1|Value2],Value2>(value)+  } in if (present(value2)) {+    fail("Failed")+  } }  @value interface Base {}@@ -362,24 +321,18 @@   refines Base } -define Test {-  run () {-    [Value1|Value2] value <- Value1.create()-    scoped {-      optional Value2 value2 <- reduce<[Value1|Value2],Value2>(value)-    } in if (present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce success to intersect" {+  success } --testcase "reduce success to intersect" {-  success Test.run()+unittest test {+  Value value <- Value.create()+  scoped {+    optional [Base1&Base2] value2 <- reduce<Value,[Base1&Base2]>(value)+  } in if (!present(value2)) {+    fail("Failed")+  } }  @value interface Base1 {}@@ -399,24 +352,18 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    scoped {-      optional [Base1&Base2] value2 <- reduce<Value,[Base1&Base2]>(value)-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce fail to intersect" {+  success } --testcase "reduce fail to intersect" {-  success Test.run()+unittest test {+  Value value <- Value.create()+  scoped {+    optional [Base1&Base2] value2 <- reduce<Value,[Base1&Base2]>(value)+  } in if (present(value2)) {+    fail("Failed")+  } }  @value interface Base1 {}@@ -435,24 +382,18 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    scoped {-      optional [Base1&Base2] value2 <- reduce<Value,[Base1&Base2]>(value)-    } in if (present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce success union to intersect" {+  success } --testcase "reduce success union to intersect" {-  success Test.run()+unittest test {+  [Value1|Value2] value <- Value2.create()+  scoped {+    optional [Base1&Base2] value2 <- reduce<[Value1|Value2],[Base1&Base2]>(value)+  } in if (!present(value2)) {+    fail("Failed")+  } }  @value interface Base1 {}@@ -477,24 +418,18 @@   } } -define Test {-  run () {-    [Value1|Value2] value <- Value2.create()-    scoped {-      optional [Base1&Base2] value2 <- reduce<[Value1|Value2],[Base1&Base2]>(value)-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce fail union to intersect" {+  success } --testcase "reduce fail union to intersect" {-  success Test.run()+unittest test {+  [Value1|Value2] value <- Value2.create()+  scoped {+    optional [Base1&Base2] value2 <- reduce<[Value1|Value2],[Base1&Base2]>(value)+  } in if (present(value2)) {+    fail("Failed")+  } }  @value interface Base1 {}@@ -518,24 +453,18 @@   } } -define Test {-  run () {-    [Value1|Value2] value <- Value2.create()-    scoped {-      optional [Base1&Base2] value2 <- reduce<[Value1|Value2],[Base1&Base2]>(value)-    } in if (present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce success intersect to union" {+  success } --testcase "reduce success intersect to union" {-  success Test.run()+unittest test {+  [Value1&Value2] value <- Data.create()+  scoped {+    optional [Base1|Base2] value2 <- reduce<[Value1&Value2],[Base1|Base2]>(value)+  } in if (!present(value2)) {+    fail("Failed")+  } }  @value interface Base1 {}@@ -561,24 +490,18 @@   } } -define Test {-  run () {-    [Value1&Value2] value <- Data.create()-    scoped {-      optional [Base1|Base2] value2 <- reduce<[Value1&Value2],[Base1|Base2]>(value)-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce fail intersect to union" {+  success } --testcase "reduce fail intersect to union" {-  success Test.run()+unittest test {+  [Value1&Value2] value <- Data.create()+  scoped {+    optional [Base1|Base2] value2 <- reduce<[Value1&Value2],[Base1|Base2]>(value)+  } in if (present(value2)) {+    fail("Failed")+  } }  @value interface Base1 {}@@ -602,24 +525,18 @@   } } -define Test {-  run () {-    [Value1&Value2] value <- Data.create()-    scoped {-      optional [Base1|Base2] value2 <- reduce<[Value1&Value2],[Base1|Base2]>(value)-    } in if (present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce succeeds to covariant any" {+  success } --testcase "reduce succeeds to covariant any" {-  success Test.run()+unittest test {+  Value<String> value <- Value<String>.create()+  scoped {+    optional Value<any> value2 <- reduce<Value<String>,Value<any>>(value)+  } in if (!present(value2)) {+    fail("Failed")+  } }  concrete Value<|#x> {@@ -632,24 +549,18 @@   } } -define Test {-  run () {-    Value<Test> value <- Value<Test>.create()-    scoped {-      optional Value<any> value2 <- reduce<Value<Test>,Value<any>>(value)-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce succeeds to contravariant all" {+  success } --testcase "reduce succeeds to contravariant all" {-  success Test.run()+unittest test {+  Value<String> value <- Value<String>.create()+  scoped {+    optional Value<all> value2 <- reduce<Value<String>,Value<all>>(value)+  } in if (!present(value2)) {+    fail("Failed")+  } }  concrete Value<#x|> {@@ -662,24 +573,18 @@   } } -define Test {-  run () {-    Value<Test> value <- Value<Test>.create()-    scoped {-      optional Value<all> value2 <- reduce<Value<Test>,Value<all>>(value)-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce fails to invariant any" {+  success } --testcase "reduce fails to invariant any" {-  success Test.run()+unittest test {+  Value<String> value <- Value<String>.create()+  scoped {+    optional Value<any> value2 <- reduce<Value<String>,Value<any>>(value)+  } in if (present(value2)) {+    fail("Failed")+  } }  concrete Value<#x> {@@ -692,24 +597,18 @@   } } -define Test {-  run () {-    Value<Test> value <- Value<Test>.create()-    scoped {-      optional Value<any> value2 <- reduce<Value<Test>,Value<any>>(value)-    } in if (present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce succeeds from covariant all" {+  success } --testcase "reduce succeeds from covariant all" {-  success Test.run()+unittest test {+  Value<all> value <- Value<all>.create()+  scoped {+    optional Value<String> value2 <- reduce<Value<all>,Value<String>>(value)+  } in if (!present(value2)) {+    fail("Failed")+  } }  concrete Value<|#x> {@@ -722,24 +621,18 @@   } } -define Test {-  run () {-    Value<all> value <- Value<all>.create()-    scoped {-      optional Value<Test> value2 <- reduce<Value<all>,Value<Test>>(value)-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce succeeds from contravariant any" {+  success } --testcase "reduce succeeds from contravariant any" {-  success Test.run()+unittest test {+  Value<any> value <- Value<any>.create()+  scoped {+    optional Value<String> value2 <- reduce<Value<any>,Value<String>>(value)+  } in if (!present(value2)) {+    fail("Failed")+  } }  concrete Value<#x|> {@@ -752,24 +645,18 @@   } } -define Test {-  run () {-    Value<any> value <- Value<any>.create()-    scoped {-      optional Value<Test> value2 <- reduce<Value<any>,Value<Test>>(value)-    } in if (!present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce fails from invariant all" {+  success } --testcase "reduce fails from invariant all" {-  success Test.run()+unittest test {+  Value<all> value <- Value<all>.create()+  scoped {+    optional Value<String> value2 <- reduce<Value<all>,Value<String>>(value)+  } in if (present(value2)) {+    fail("Failed")+  } }  concrete Value<#x> {@@ -782,22 +669,7 @@   } } -define Test {-  run () {-    Value<all> value <- Value<all>.create()-    scoped {-      optional Value<Test> value2 <- reduce<Value<all>,Value<Test>>(value)-    } in if (present(value2)) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "bad instance in reduce param" {   error   require "Test"@@ -805,6 +677,10 @@   require "Equals" } +unittest test {+  \ reduce<Value<Test>,Formatted>(empty)+}+ @value interface Value<#x> {   #x defines Equals<#x> }@@ -817,19 +693,15 @@   call () {} } -define Test {-  run () {-    \ reduce<Value<Test>,Formatted>(empty)-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce from interface" {+  success } --testcase "reduce from interface" {-  success Test.run()+unittest test {+  if (!present(reduce<Base1,Base0>(Value.create()))) {+    fail("Failed")+  } }  @value interface Base0 {@@ -850,21 +722,18 @@   } } -define Test {-  run () {-    if (!present(reduce<Base1,Base0>(Value.create()))) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "reduce with internal override" {+  success } --testcase "reduce with internal override" {-  success Test.run()+unittest test {+  if (!present(reduce<Value,Base2<Base0>>(Value.create()))) {+    fail("Failed")+  }+  if (present(reduce<Value,Base2<Base1>>(Value.create()))) {+    fail("Failed")+  } }  @value interface Base0 {}@@ -886,19 +755,4 @@   create () {     return Value{ }   }-}--define Test {-  run () {-    if (!present(reduce<Value,Base2<Base0>>(Value.create()))) {-      fail("Failed")-    }-    if (present(reduce<Value,Base2<Base1>>(Value.create()))) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> () }
tests/regressions.0rt view
@@ -17,7 +17,11 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "Issue #73 is fixed" {-  success empty+  success+}++unittest test {+  \ empty }  concrete Type1<#x> {
tests/scoped.0rt view
@@ -17,203 +17,156 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "scoped unconditional" {-  success Test.run()+  success } -@value interface Value {}--define Test {-  run () {-    scoped {-      Int x <- 1-    } in {-      x <- 2-    }+unittest test {+  scoped {+    Int x <- 1+  } in {+    x <- 2   } } -concrete Test {-  @type run () -> ()-} - testcase "unconditional has scoping" {   error   require "x" } -@value interface Value {}--define Test {-  run () {-    scoped {-    } in {-      Int x <- 1-    }-    x <- 2+unittest test {+  scoped {+  } in {+    Int x <- 1   }-}--concrete Test {-  @type run () -> ()+  x <- 2 }   testcase "return inside scope" {-  success Test.run()+  compiles } --@value interface Value {}+concrete Value {} -define Test {+define Value {   @value process () -> (optional Value)   process () {     scoped {       return empty     } in \ empty   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "return from scoped" {-  success Test.run()+  compiles } -@value interface Value {}+concrete Value {} -define Test {+define Value {   @value process () -> (optional Value)   process () {     scoped {     } in return empty   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "update clashes with scoped" {   error   require "x" } -define Test {-  run () {-    scoped {-      Int x <- 2-    } in while (false) {-    } update {-      Int x <- 1-    }+unittest test {+  scoped {+    Int x <- 2+  } in while (false) {+  } update {+    Int x <- 1   } } -concrete Test {-  @type run () -> ()-} - testcase "assign inside scope" {-  success Test.run()+  compiles } -@value interface Value {}+concrete Value {} -define Test {+define Value {   @value process () -> (optional Value)   process () (value) {     scoped {       value <- empty     } in \ empty   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "assign from scoped" {-  success Test.run()+  compiles } -@value interface Value {}+concrete Value {} -define Test {+define Value {   @value process () -> (optional Value)   process () (value) {     scoped {     } in value <- empty   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "simple cleanup" {-  success Test.run()+  success } -define Test {-  run () {-    Int value <- 0-    scoped {-      value <- 1-    } cleanup {-      value <- 2-    } in value <- 3-    if (value != 2) {-      fail(value)-    }+unittest test {+  Int value <- 0+  scoped {+    value <- 1+  } cleanup {+    value <- 2+  } in value <- 3+  if (value != 2) {+    fail(value)   } } -concrete Test {-  @type run () -> ()-} - testcase "name clash in cleanup" {   error   require "value.+already defined" } -define Test {-  run () {-    scoped {-      Int value <- 1-    } cleanup {-      Int value <- 2-    } in \ empty-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  scoped {+    Int value <- 1+  } cleanup {+    Int value <- 2+  } in \ empty }   testcase "cleanup before return" {-  success Test.run()+  success } +unittest test {+  Value value <- Value.create()+  Int value1 <- value.call()+  if (value1 != 2) {+    fail(value1)+  }+  Int value2 <- value.get()+  if (value2 != 3) {+    fail(value2)+  }+}+ concrete Value {   @type create () -> (Value)   @value call () -> (Int)@@ -241,58 +194,41 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    Int value1 <- value.call()-    if (value1 != 2) {-      fail(value1)-    }-    Int value2 <- value.get()-    if (value2 != 3) {-      fail(value2)-    }-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "positional return sets named returns for cleanup" {-  crash Test.run()+  crash   require "message"   exclude "failed" } -define Test {+unittest test {+  String value, _ <- Test.get()+  fail(value)+}++concrete Test {   // Using a second return ensures that assignment works properly when the   // ReturnTuple is constructed during assignment.   @type get () -> (String,Int)+}++define Test {   get () (value,value2) {     value <- "failed"     cleanup {       fail(value)     } in return "message", 1   }--  run () {-    String value, _ <- get()-    fail(value)-  } } -concrete Test {-  @type run () -> ()-} - testcase "cannot refer to cleanup variables" {   error   require "value.+not defined" } +concrete Test {}+ define Test {   @type get () -> (Int)   get () (value) {@@ -301,23 +237,25 @@       Int value2 <- 1     } in return value2   }--  run () {-    \ get()-  } } -concrete Test {-  @type run () -> ()++testcase "cleanup skipped in scoped return" {+  success } +unittest test {+    Int value <- Test.get()+    if (value != 1) {+      fail(value)+    }+} -testcase "cleanup skipped in scoped return" {-  success Test.run()+concrete Test {+  @type get () -> (Int) }  define Test {-  @type get () -> (Int)   get () {     Int value <- 0     scoped {@@ -327,59 +265,66 @@       value <- 2     } in return 3   }--  run () {-    Int value <- get()-    if (value != 1) {-      fail(value)-    }-  } } -concrete Test {-  @type run () -> ()-} - testcase "multiple cleanup" {-  success Test.run()+  success } -define Test {-  run () {-    Int value1 <- 0-    Int value2 <- 0-    Int value3 <- 0-    scoped {-    } cleanup {-      value1 <- 1-      value2 <- 1-    } in scoped {-    } cleanup {-      value2 <- 2-      value3 <- 2-    } in \ empty-    if (value1 != 1) {-      fail(value1)-    }-    if (value2 != 1) {-      fail(value2)-    }-    if (value3 != 2) {-      fail(value3)-    }+unittest test {+  Int value1 <- 0+  Int value2 <- 0+  Int value3 <- 0+  scoped {+  } cleanup {+    value1 <- 1+    value2 <- 1+  } in scoped {+  } cleanup {+    value2 <- 2+    value3 <- 2+  } in \ empty+  if (value1 != 1) {+    fail(value1)   }-}--concrete Test {-  @type run () -> ()+  if (value2 != 1) {+    fail(value2)+  }+  if (value3 != 2) {+    fail(value3)+  } }   testcase "multiple cleanup with return" {-  success Test.run()+  success } +unittest test {+  Value value <- Value.create()+  Int value1, Int value2, Int value3 <- value.call()+  if (value1 != 1) {+    fail(value1)+  }+  if (value2 != 1) {+    fail(value2)+  }+  if (value3 != 1) {+    fail(value3)+  }+  value1, value2, value3 <- value.get()+  if (value1 != 2) {+    fail(value1)+  }+  if (value2 != 2) {+    fail(value2)+  }+  if (value3 != 3) {+    fail(value3)+  }+}+ concrete Value {   @type create () -> (Value)   @value call () -> (Int,Int,Int)@@ -415,53 +360,17 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    Int value1, Int value2, Int value3 <- value.call()-    if (value1 != 1) {-      fail(value1)-    }-    if (value2 != 1) {-      fail(value2)-    }-    if (value3 != 1) {-      fail(value3)-    }-    value1, value2, value3 <- value.get()-    if (value1 != 2) {-      fail(value1)-    }-    if (value2 != 2) {-      fail(value2)-    }-    if (value3 != 3) {-      fail(value3)-    }-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "cleanup cannot refer to later variables" {   error   require "value.+not defined" } -define Test {-  run () {-    scoped {-    } cleanup {-      value <- 1-    } in Int value <- 2-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  scoped {+  } cleanup {+    value <- 1+  } in Int value <- 2 }  @@ -470,136 +379,108 @@   require "value.+not defined" } -define Test {-  run () {-    scoped {-    } cleanup {-      Int value <- 0-    } in scoped {-    } cleanup {-      value <- 1-    } in \ empty-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  scoped {+  } cleanup {+    Int value <- 0+  } in scoped {+  } cleanup {+    value <- 1+  } in \ empty }   testcase "no name clash in nested scope with return" {-  success Test.run()-}--define Test {-  run () {-    scoped {-    } cleanup {-      Int value <- 0-    } in scoped {-    } cleanup {-      Int value <- 1-    } in return _-  }+  success } -concrete Test {-  @type run () -> ()+unittest test {+  scoped {+  } cleanup {+    Int value <- 0+  } in scoped {+  } cleanup {+    Int value <- 1+  } in return _ }   testcase "cleanup skipped for fail" {-  crash Test.run()+  crash   require "scoped" } -define Test {-  run () {-    scoped {-      String message <- "scoped"-    } cleanup {-      message <- "cleanup"-    } in fail(message)-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  scoped {+    String message <- "scoped"+  } cleanup {+    message <- "cleanup"+  } in fail(message) }   testcase "cleanup not applied to returns outside of scope" {-  success Test.run()+  success } -define Test {-  run () {-    Int value <- 0-    scoped {-    } cleanup {-      if (value != 0) {-        fail(value)-      }-    } in \ empty--    value <- 1-    return _-  }-}+unittest test {+  Int value <- 0+  scoped {+  } cleanup {+    if (value != 0) {+      fail(value)+    }+  } in \ empty -concrete Test {-  @type run () -> ()+  value <- 1+  return _ }   testcase "cleanup unconditional" {-  success Test.run()+  success } -@value interface Value {}--define Test {-  run () {-    scoped {-      Int x <- 1-    } in {-      \ x-    }+unittest test {+  scoped {+    Int x <- 1+  } in {+    \ x   } } -concrete Test {-  @type run () -> ()-} - testcase "scoped empty blocks" {-  success Test.run()+  success } -@value interface Value {}--define Test {-  run () {-    scoped {-      // empty-    } cleanup {-      // empty-    } in {-      // empty-    }+unittest test {+  scoped {+    // empty+  } cleanup {+    // empty+  } in {+    // empty   } } -concrete Test {-  @type run () -> ()-} - testcase "just cleanup" {-  success Test.run()+  success } +unittest test {+  Value value <- Value.create()+  Int value1 <- value.postIncrement()+  if (value1 != 0) {+    fail(value1)+  }+  Int value2 <- value.get()+  if (value2 != 1) {+    fail(value2)+  }+}+ concrete Value {   @type create () -> (Value)   @value postIncrement () -> (Int)@@ -624,27 +505,9 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    Int value1 <- value.postIncrement()-    if (value1 != 0) {-      fail(value1)-    }-    Int value2 <- value.get()-    if (value2 != 1) {-      fail(value2)-    }-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "separate trace context for cleanup" {-  crash Test.run()+  crash   require "Failed"   require "cleanup block"   require "Test\.run"@@ -652,6 +515,10 @@   exclude "Test\.run.+Failed" } +unittest test {+  \ Test.run()+}+ define Test {   run () {     cleanup {@@ -666,47 +533,59 @@   testcase "partial cleanup with while and break" {-  success Test.run()+  success } -define Test {-  run () {-    Int x <- 0-    Int y <- 0-    Int z <- 0-    cleanup {-      x <- 1-    } in {-      while (true) {+unittest test {+  Int x <- 0+  Int y <- 0+  Int z <- 0+  cleanup {+    x <- 1+  } in {+    while (true) {+      cleanup {+        y <- 2+      } in if (true) {         cleanup {-          y <- 2+          z <- 3         } in if (true) {-          cleanup {-            z <- 3-          } in if (true) {-            break-          }+          break         }       }-      \ Testing.check<?>(x,0)-      \ Testing.check<?>(y,2)-      \ Testing.check<?>(z,3)     }-    \ Testing.check<?>(x,1)-    \ Testing.check<?>(y,2)-    \ Testing.check<?>(z,3)+    \ Testing.checkEquals<?>(x,0)+    \ Testing.checkEquals<?>(y,2)+    \ Testing.checkEquals<?>(z,3)   }-}--concrete Test {-  @type run () -> ()+  \ Testing.checkEquals<?>(x,1)+  \ Testing.checkEquals<?>(y,2)+  \ Testing.checkEquals<?>(z,3) }   testcase "full cleanup with while and return" {-  success Test.run()+  success } +unittest test {+  Value value <- Value.create()+  scoped {+    Int x, Int y, Int z <- value.call()+  } in {+    \ Testing.checkEquals<?>(x,0)+    \ Testing.checkEquals<?>(y,0)+    \ Testing.checkEquals<?>(z,0)+  }+  scoped {+    Int x, Int y, Int z <- value.get()+  } in {+    \ Testing.checkEquals<?>(x,1)+    \ Testing.checkEquals<?>(y,2)+    \ Testing.checkEquals<?>(z,3)+  }+}+ concrete Value {   @type create () -> (Value)   @value call () -> (Int,Int,Int)@@ -744,36 +623,14 @@   } } -define Test {-  run () {-    Value value <- Value.create()-    scoped {-      Int x, Int y, Int z <- value.call()-    } in {-      \ Testing.check<?>(x,0)-      \ Testing.check<?>(y,0)-      \ Testing.check<?>(z,0)-    }-    scoped {-      Int x, Int y, Int z <- value.get()-    } in {-      \ Testing.check<?>(x,1)-      \ Testing.check<?>(y,2)-      \ Testing.check<?>(z,3)-    }-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "named return cannot be modified in cleanup" {   error   require compiler "assign.+value" } +concrete Test {}+ define Test {   @type get () -> (String)   get () (value) {@@ -781,20 +638,16 @@       value <- "error"     } in return "message"   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "positional return not allowed in cleanup" {   error   require compiler "return.+cleanup" } +concrete Test {}+ define Test {   @type get () -> (Int)   get () (value) {@@ -802,28 +655,16 @@       return 0     } in \ empty   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "default return not allowed in cleanup" {   error   require compiler "return.+cleanup" } -define Test {-  run () {-    cleanup {-      return _-    } in \ empty-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  cleanup {+    return _+  } in \ empty }
tests/simple.0rt view
@@ -16,6 +16,17 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] +testcase "basic compiles test" {+  compiles+  require compiler "unreachable"+}++unittest test {+  return _+  \ empty+}++ testcase "basic error test" {   error   require compiler "category.+undefined"@@ -36,43 +47,37 @@   testcase "basic crash test" {-  crash Test.execute()-  require stderr "/testcase:"+  crash+  require stderr "testcase:"   require stderr "failure message!!!"   exclude stdout "failure message!!!" } -concrete Test {-  @type execute () -> ()-}--define Test {-  execute () {-    // NOTE: "!!!" is important here because it also tests mixing of escaped and-    // unescaped characters when handling string literals.-    fail("failure message!!!")-  }+unittest test {+  // NOTE: "!!!" is important here because it also tests mixing of escaped and+  // unescaped characters when handling string literals.+  fail("failure message!!!") }   testcase "basic success test" {-  success Test.execute()-}--concrete Test {-  @type execute () -> ()+  success } -define Test {-  execute () { }+unittest test {+  return _ }   testcase "minimal linking works properly" {-  success empty+  success } +unittest test {+  \ empty+} + testcase "attempt to define outside of this module" {   error   require "String"@@ -85,11 +90,11 @@   testcase "no deadlock with recursive type" {-  success Test.execute()+  success } -concrete Test {-  @type execute () -> ()+unittest test {+  \ Type<Type<Type<Int>>>.call() }  concrete Type<#x> {@@ -100,23 +105,11 @@   call () {} } -define Test {-  execute () {-    \ Type<Type<Type<Int>>>.call()-  }-} - testcase "ModuleOnly is visible to tests" {-  success Test.execute()-}--concrete Test {-  @type execute () -> ()+  success } -define Test {-  execute () {-    optional ModuleOnly value <- empty-  }+unittest test {+  optional ModuleOnly value <- empty }
tests/templates/tests.0rt view
@@ -17,8 +17,12 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "template compiles to binary" {-  crash Test.run()+  crash   require "Templated\.create is not implemented"+}++unittest test {+  \ Test.run() }  define Test {
tests/tracing.0rt view
@@ -17,19 +17,21 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "NoTrace skips tracing" {-  crash Test.run()+  crash   require "message"-  require "Test\.run"   require "Test\.error"   exclude "Test\.noTrace" } -define Test {-  run () {-    \ noTrace()-  }+unittest test {+  \ Test.noTrace()+} +concrete Test {   @type noTrace () -> ()+}++define Test {   noTrace () { $NoTrace$     \ error()   }@@ -40,17 +42,18 @@   } } -concrete Test {-  @type run () -> ()-} - testcase "TraceCreation captures trace" {-  crash Test.run()+  crash   require "message"   require "Type.+created at" } +unittest test {+  Type value <- Type.create()+  \ value.call()+}+ concrete Type {   @type create () -> (Type)   @value call () -> ()@@ -66,39 +69,32 @@   } } -define Test {-  run () {-    Type value <- Type.create()-    \ value.call()-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "TraceCreation ignored in @type" {-  success Test.run()+  compiles   require compiler "tracing ignored" } -define Test {-  run () { $TraceCreation$ }-}+concrete Test {} -concrete Test {+define Test {   @type run () -> ()+  run () { $TraceCreation$ } }   testcase "TraceCreation still works with NoTrace" {-  crash Test.run()+  crash   require "message"   require "Type.+created at"   exclude "Type\.call" } +unittest test {+  Type value <- Type.create()+  \ value.call()+}+ concrete Type {   @type create () -> (Type)   @value call () -> ()@@ -109,30 +105,24 @@     return Type{ }   } -  call ()  { $NoTrace$ $TraceCreation$+  call () { $NoTrace$ $TraceCreation$     fail("message")   } } -define Test {-  run () {-    Type value <- Type.create()-    \ value.call()-  }-} -concrete Test {-  @type run () -> ()-}-- testcase "TraceCreation only uses the latest" {-  crash Test.run()+  crash   require "message"   require "Type1.+created at"   exclude "Type2.+created at" } +unittest test {+  Type2 value <- Type2.create()+  \ value.call()+}+ concrete Type1 {   @type create () -> (Type1)   @value call () -> ()@@ -163,15 +153,4 @@   call ()  { $TraceCreation$     \ value.call()   }-}--define Test {-  run () {-    Type2 value <- Type2.create()-    \ value.call()-  }-}--concrete Test {-  @type run () -> () }
tests/typename.0rt view
@@ -16,228 +16,106 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -testcase "String typename" {-  success Test.run()+testcase "builtin typenames" {+  success } -define Test {-  run () {-    Formatted name <- typename<String>()-    if (name.formatted() != "String") {-      fail(name)-    }+unittest string {+  Formatted name <- typename<String>()+  if (name.formatted() != "String") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "Int typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<Int>()-    if (name.formatted() != "Int") {-      fail(name)-    }+unittest int {+  Formatted name <- typename<Int>()+  if (name.formatted() != "Int") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "Char typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<Char>()-    if (name.formatted() != "Char") {-      fail(name)-    }+unittest char {+  Formatted name <- typename<Char>()+  if (name.formatted() != "Char") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "Float typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<Float>()-    if (name.formatted() != "Float") {-      fail(name)-    }+unittest float {+  Formatted name <- typename<Float>()+  if (name.formatted() != "Float") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "Bool typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<Bool>()-    if (name.formatted() != "Bool") {-      fail(name)-    }+unittest bool {+  Formatted name <- typename<Bool>()+  if (name.formatted() != "Bool") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "Formatted typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<Formatted>()-    if (name.formatted() != "Formatted") {-      fail(name)-    }+unittest formatted {+  Formatted name <- typename<Formatted>()+  if (name.formatted() != "Formatted") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "ReadPosition typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<ReadPosition<Char>>()-    if (name.formatted() != "ReadPosition<Char>") {-      fail(name)-    }+unittest readPosition {+  Formatted name <- typename<ReadPosition<Char>>()+  if (name.formatted() != "ReadPosition<Char>") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "any typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<any>()-    if (name.formatted() != "any") {-      fail(name)-    }+unittest anyType {+  Formatted name <- typename<any>()+  if (name.formatted() != "any") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "all typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<all>()-    if (name.formatted() != "all") {-      fail(name)-    }+unittest allType {+  Formatted name <- typename<all>()+  if (name.formatted() != "all") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "intersect typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<[String&Int]>()-    if (name.formatted() != "[Int&String]") {-      fail(name)-    }+unittest intersect {+  Formatted name <- typename<[String&Int]>()+  if (name.formatted() != "[Int&String]") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "union typename" {-  success Test.run()-}--define Test {-  run () {-    Formatted name <- typename<[String|Int]>()-    if (name.formatted() != "[Int|String]") {-      fail(name)-    }+unittest union {+  Formatted name <- typename<[String|Int]>()+  if (name.formatted() != "[Int|String]") {+    fail(name)   } } -concrete Test {-  @type run () -> ()-}---testcase "param typename" {-  success Test.run()-}- @value interface Value<#x> {}  @value interface Type<#x,#y> {} -define Test {-  @category getTypename<#x,#y> () -> (Formatted)+define Wrapped {   getTypename () {     return typename<Type<#x,#y>>()   }+} -  run () {-    Formatted name <- getTypename<String,Value<Int>>()-    if (name.formatted() != "Type<String,Value<Int>>") {-      fail(name)-    }-  }+concrete Wrapped {+  @category getTypename<#x,#y> () -> (Formatted) } -concrete Test {-  @type run () -> ()+unittest param {+  Formatted name <- Wrapped:getTypename<String,Value<Int>>()+  if (name.formatted() != "Type<String,Value<Int>>") {+    fail(name)+  } }  @@ -248,24 +126,14 @@   require "Equals" } -@value interface Value<#x> {-  #x defines Equals<#x>-}--concrete Call {-  @type call<#x> () -> ()+unittest test {+  \ typename<Value<Test>>() } -define Call {-  call () {}+@value interface Value<#x> {+  #x defines Equals<#x> } -define Test {-  run () {-    \ typename<Value<Test>>()-  }-}+concrete Test {} -concrete Test {-  @type run () -> ()-}+define Test {}
tests/unary-functions.0rt view
@@ -17,55 +17,60 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "category unary" {-  success Test.run()+  success } -define Test {-  @category neg (Int) -> (Int)-  neg (x) {-    return -x-  }--  run () {-    Int value <- `Test:neg` 2-    if (value != -2) {-      fail(value)-    }+unittest test {+  Int value <- `Test:neg` 2+  if (value != -2) {+    fail(value)   } }  concrete Test {-  @type run () -> ()-}---testcase "type unary" {-  success Test.run()+  @category neg (Int) -> (Int) }  define Test {-  @type neg (Int) -> (Int)   neg (x) {     return -x   }+} -  run () {-    Int value <- `Test.neg` 2-    if (value != -2) {-      fail(value)-    }++testcase "type unary" {+  success+}++unittest test {+  Int value <- `Test.neg` 2+  if (value != -2) {+    fail(value)   } }  concrete Test {-  @type run () -> ()+  @type neg (Int) -> (Int) } +define Test {+  neg (x) {+    return -x+  }+} + testcase "value unary" {-  success Test.run()+  success } +unittest test {+  Int value <- `Arithmetic.create().neg` 2+  if (value != -2) {+    fail(value)+  }+}+ concrete Arithmetic {   @type create () -> (Arithmetic)   @value neg (Int) -> (Int)@@ -81,22 +86,13 @@   } } -define Test {-  run () {-    Int value <- `Arithmetic.create().neg` 2-    if (value != -2) {-      fail(value)-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "unqualified unary" {+  success } --testcase "unqualified unary" {-  success Test.run()+unittest test {+  \ Test.run() }  define Test {@@ -119,28 +115,27 @@   testcase "unary function with infix function" {-  success Test.run()+  success } -define Test {+unittest test {+  Int value <- 1 `Test:add` `Test:neg` 2+  if (value != -1) {+    fail(value)+  }+}++concrete Test {   @category add (Int,Int) -> (Int)+  @category neg (Int) -> (Int)+}++define Test {   add (x,y) {     return x + y   } -  @type neg (Int) -> (Int)   neg (x) {     return -x   }--  run () {-    Int value <- 1 `add` `neg` 2-    if (value != -1) {-      fail(value)-    }-  }-}--concrete Test {-  @type run () -> () }
tests/unreachable.0rt view
@@ -17,68 +17,58 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "warning statement after fail" {-  success Test.run()+  compiles   require compiler "unreachable" } +concrete Test {}+ define Test {   @category failedReturn () -> (Int)   failedReturn () {     fail("Failed")     return 1   }--  run () {} } -concrete Test {-  @type run () -> ()-}- testcase "unreachable not compiled" {-  success Test.run()+  compiles } +concrete Test {}+ define Test {   @category failedReturn () -> (Int)   failedReturn () {     fail("Failed")     \ foo()   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "warning statement after return" {-  success Test.run()+  compiles   require compiler "unreachable" } +concrete Test {}+ define Test {   @category failedReturn () -> (Int)   failedReturn () {     return 0     return 1   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "warning statement after conditional return" {-  success Test.run()+  compiles   require compiler "unreachable" } +concrete Test {}+ define Test {   @category failedReturn () -> (Int)   failedReturn () {@@ -89,20 +79,16 @@     }     return 3   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "warning statement after scoped return" {-  success Test.run()+  compiles   require compiler "unreachable" } +concrete Test {}+ define Test {   @category failedReturn () -> (Int)   failedReturn () {@@ -110,23 +96,24 @@       return 1     } in return 2   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "warning statement after cleanup fail" {-  crash Test.run()+  crash   require compiler "unreachable"   require "message" } -define Test {+unittest test {+  \ Test:failedReturn()+}++concrete Test {   @category failedReturn () -> (Int)+}++define Test {   failedReturn () {     scoped {     } cleanup {@@ -134,25 +121,24 @@     } in \ empty     return 2   }--  run () {-    \ failedReturn()-  } } -concrete Test {-  @type run () -> ()-} - testcase "warning statement in cleanup after scoped fail" {-  crash Test.run()+  crash   require compiler "unreachable"   require "message" } -define Test {+unittest test {+  \ Test:failedReturn()+}++concrete Test {   @category failedReturn () -> ()+}++define Test {   failedReturn () {     scoped {       fail("message")@@ -160,74 +146,53 @@       \ empty     } in {}   }--  run () {-    \ failedReturn()-  } } -concrete Test {-  @type run () -> ()-} - testcase "warning statement in cleanup after in fail" {-  crash Test.run()+  crash   require compiler "unreachable"   require "message" } -define Test {+unittest test {+  \ Test:failedReturn()+}++concrete Test {   @category failedReturn () -> ()+}++define Test {   failedReturn () {     cleanup {       \ empty     } in fail("message")   }--  run () {-    \ failedReturn()-  } } -concrete Test {-  @type run () -> ()-} - testcase "warning statement after break" {-  success Test.run()+  compiles   require compiler "unreachable" } -define Test {-  run () {-    while (false) {-      break-      fail("Failed")-    }+unittest test {+  while (false) {+    break+    fail("Failed")   } } -concrete Test {-  @type run () -> ()-} - testcase "warning statement after continue" {-  success Test.run()+  compiles   require compiler "unreachable" } -define Test {-  run () {-    while (false) {-      continue-      fail("Failed")-    }+unittest test {+  while (false) {+    continue+    fail("Failed")   }-}--concrete Test {-  @type run () -> () }
tests/value-init.0rt view
@@ -17,9 +17,17 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "value init in @category member" {-  success Test.run()+  success } +unittest test {+  \ Test.run()+}++concrete Test {+  @type run () -> ()+}+ define Test {   @value Int value   @category Test singleton <- Test{ 3 }@@ -30,21 +38,21 @@   }    run () {-    if (singleton.get() != 3) {-      fail(singleton.get())-    }   } } -concrete Test {-  @type run () -> ()-} - testcase "init value same type from @type" {-  success Test.run()+  success } +unittest test {+  Value<Int> value <- Value<Int>.create(1)+  if (value.get() != 1) {+    fail("Failed")+  }+}+ concrete Value<#x> {   @type create (#x) -> (Value<#x>)   @value get () -> (#x)@@ -62,22 +70,16 @@   } } -define Test {-  run () {-    Value<Int> value <- Value<Int>.create(1)-    if (value.get() != 1) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "init value different type from @type" {+  success } --testcase "init value different type from @type" {-  success Test.run()+unittest test {+  Value<Int> value <- Value<String>.create<Int>(1)+  if (value.get() != 1) {+    fail("Failed")+  } }  concrete Value<#x> {@@ -97,22 +99,16 @@   } } -define Test {-  run () {-    Value<Int> value <- Value<String>.create<Int>(1)-    if (value.get() != 1) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "init value same type from @value" {+  success } --testcase "init value same type from @value" {-  success Test.run()+unittest test {+  Value<Int> value <- Value<Int>.create(2).create2(1)+  if (value.get() != 1) {+    fail("Failed")+  } }  concrete Value<#x> {@@ -137,22 +133,16 @@   } } -define Test {-  run () {-    Value<Int> value <- Value<Int>.create(2).create2(1)-    if (value.get() != 1) {-      fail("Failed")-    }-  }-} -concrete Test {-  @type run () -> ()+testcase "init value different type from @value" {+  success } --testcase "init value different type from @value" {-  success Test.run()+unittest test {+  Value<Int> value <- Value<String>.create("x").create2<Int>(1)+  if (value.get() != 1) {+    fail("Failed")+  } }  concrete Value<#x> {@@ -175,17 +165,4 @@   get () {     return value   }-}--define Test {-  run () {-    Value<Int> value <- Value<String>.create("x").create2<Int>(1)-    if (value.get() != 1) {-      fail("Failed")-    }-  }-}--concrete Test {-  @type run () -> () }
tests/visibility.0rt view
@@ -17,7 +17,11 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "public types in private deps stay hidden" {-  success Test.run()+  success+}++unittest test {+  \ Test.run() }  // Internal is defined in visibility/internal and visibility2/internal. The
tests/while.0rt view
@@ -23,6 +23,8 @@  @value interface Value {} +concrete Test {}+ define Test {   @value process () -> (optional Value)   process () (value) {@@ -30,15 +32,9 @@       value <- empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "assign while condition" {   error   require "value.+before return"@@ -46,19 +42,15 @@  @value interface Value {} +concrete Test {}+ define Test {   @value process () -> (optional Value)   process () (value) {     while (present((value <- empty))) {}   }--  run () {} } -concrete Test {-  @type run () -> ()-}- testcase "return while" {   error   require "return"@@ -66,6 +58,8 @@  @value interface Value {} +concrete Test {}+ define Test {   @value process () -> (optional Value)   process () {@@ -73,29 +67,17 @@       return empty     }   }--  run () {} } -concrete Test {-  @type run () -> ()-} - testcase "break outside of while" {   error   require "while"   require "break" } -define Test {-  run () {-    break-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  break }  @@ -105,101 +87,65 @@   require "continue" } -define Test {-  run () {-    continue-  }-}--concrete Test {-  @type run () -> ()+unittest test {+  continue }  -testcase "while with break" {-  success Test.run()+testcase "successful while loops" {+  success } -define Test {-  run () {-    Int output <- -1-    scoped {-      Int i <- 0-      Int limit <- 5-    } in while (i < limit) {-      output <- i-      break-      fail("Failed")-    }-    if (output != 0) {-      fail("Failed")-    }+unittest withBreak {+  Int output <- -1+  scoped {+    Int i <- 0+    Int limit <- 5+  } in while (i < limit) {+    output <- i+    break+    fail("Failed")   }-}--concrete Test {-  @type run () -> ()-}---testcase "while with update" {-  success Test.run()-}--define Test {-  run () {-    Int output <- -1-    scoped {-      Int i <- 0-      Int limit <- 5-    } in while (i < limit) {-      output <- i-    } update {-      i <- i+1-    }-    if (output != 4) {-      fail("Failed")-    }+  if (output != 0) {+    fail("Failed")   } } -concrete Test {-  @type run () -> ()-}---testcase "break in update" {-  success Test.run()+unittest withUpdate {+  Int output <- -1+  scoped {+    Int i <- 0+    Int limit <- 5+  } in while (i < limit) {+    output <- i+  } update {+    i <- i+1+  }+  if (output != 4) {+    fail("Failed")+  } } -define Test {-  run () {-    Int output <- 0-    while (true) {-    } update {-      if (output > 5) {-        break-        fail("Failed")-      }-      output <- output+1-    }-    if (output != 6) {+unittest breakInUpdate {+  Int output <- 0+  while (true) {+  } update {+    if (output > 5) {+      break       fail("Failed")     }+    output <- output+1   }-}--concrete Test {-  @type run () -> ()+  if (output != 6) {+    fail("Failed")+  } } --testcase "return in update" {-  success Test.run()+concrete ReturnInUpdate {+  @type test () -> (Int) } -define Test {-  @type test () -> (Int)+define ReturnInUpdate {   test () {     Int output <- 0     while ((output <- output+1) > 0) {@@ -211,125 +157,40 @@     }     return -1   }--  run () {-    if (test() != 6) {-      fail("Failed")-    }-  } } -concrete Test {-  @type run () -> ()-}---testcase "break and continue in if/else" {-  success Test.run()-}--define Test {-  run () {-    Int i <- 0-    while (true) {-      if (i > 5) {-        break-      } else {-        continue-      }-      fail("Failed")-    } update {-      i <- i+1-    }-    if (i != 6) {-      fail("Failed")-    }+unittest returnInUpdate {+  if (ReturnInUpdate.test() != 6) {+    fail("Failed")   } } -concrete Test {-  @type run () -> ()-}---testcase "update clashes with while" {-  success Test.run()-}--define Test {-  run () {-    while (false) {-      Int x <- 2-    } update {-      Int x <- 1+unittest breakContinueInIfElse {+  Int i <- 0+  while (true) {+    if (i > 5) {+      break+    } else {+      continue     }+    fail("Failed")+  } update {+    i <- i+1   }-}--concrete Test {-  @type run () -> ()-}---testcase "while without update" {-  success Test.run()-}--define Test {-  run () {-    Int output <- -1-    scoped {-      Int i <- 0-      Int limit <- 5-    } in while (i < limit) {-      output <- i-      i <- i+1-    }-    if (output != 4) {-      fail("Failed")-    }+  if (i != 6) {+    fail("Failed")   } } -concrete Test {-  @type run () -> ()-}---testcase "while with continue and update" {-  success Test.run()-}--define Test {-  run () {-    Int output <- -1-    scoped {-      Int i <- 0-      Int limit <- 5-    } in while (i < limit) {-      output <- i-      continue-      fail("Failed")-    } update {-      i <- i+1-    }-    if (output != 4) {-      fail("Failed")-    }+unittest updateHasSeparateScope {+  while (false) {+    Int x <- 2+  } update {+    Int x <- 1   } } -concrete Test {-  @type run () -> ()-}---testcase "while with continue and without update" {-  success Test.run()-}--define Test {-  run () {+unittest noUpdate {     Int output <- -1     scoped {       Int i <- 0@@ -337,80 +198,71 @@     } in while (i < limit) {       output <- i       i <- i+1-      continue-      fail("Failed")     }     if (output != 4) {       fail("Failed")     }-  } } -concrete Test {-  @type run () -> ()-}---testcase "crash in while" {-  crash Test.run()-  require "empty"-}--define Test {-  run () {-    optional Bool test <- empty-    while (require(test)) {-      // empty-    }+unittest continueWithUpdate {+  Int output <- -1+  scoped {+    Int i <- 0+    Int limit <- 5+  } in while (i < limit) {+    output <- i+    continue+    fail("Failed")+  } update {+    i <- i+1   }-}--concrete Test {-  @type run () -> ()-}---testcase "cleanup after break" {-  success Test.run()-}--define Test {-  run () {-    Int value <- 0-    scoped {-      value <- 1-    } cleanup {-      value <- 2-    } in while (true) {-      value <- 3-      break-    }-    if (value != 2) {-      fail(value)-    }+  if (output != 4) {+    fail("Failed")   } } -concrete Test {-  @type run () -> ()+unittest continueWithoutUpdate {+  Int output <- -1+  scoped {+    Int i <- 0+    Int limit <- 5+  } in while (i < limit) {+    output <- i+    i <- i+1+    continue+    fail("Failed")+  }+  if (output != 4) {+    fail("Failed")+  } } --testcase "cleanup before return in while" {-  success Test.run()+unittest cleanupAfterBreak {+  Int value <- 0+  scoped {+    value <- 1+  } cleanup {+    value <- 2+  } in while (true) {+    value <- 3+    break+  }+  if (value != 2) {+    fail(value)+  } } -concrete Value {-  @type create () -> (Value)+concrete CleanupBeforeReturn {+  @type create () -> (CleanupBeforeReturn)   @value call () -> (Int)   @value get () -> (Int) } -define Value {+define CleanupBeforeReturn {   @value Int value    create () {-    return Value{ 0 }+    return CleanupBeforeReturn{ 0 }   }    call () {@@ -430,16 +282,33 @@   } } +unittest cleanupBeforeReturn {+  CleanupBeforeReturn value <- CleanupBeforeReturn.create()+  Int value1 <- value.call()+  if (value1 != 2) {+    fail(value1)+  }+  Int value2 <- value.get()+  if (value2 != 3) {+    fail(value2)+  }+}+++testcase "crash in while" {+  crash+  require "empty"+}++unittest test {+  \ Test.run()+}+ define Test {   run () {-    Value value <- Value.create()-    Int value1 <- value.call()-    if (value1 != 2) {-      fail(value1)-    }-    Int value2 <- value.get()-    if (value2 != 3) {-      fail(value2)+    optional Bool test <- empty+    while (require(test)) {+      // empty     }   } }
zeolite-lang.cabal view
@@ -1,7 +1,7 @@ cabal-version:       2.2  name:                zeolite-lang-version:             0.9.0.0+version:             0.10.0.0 synopsis:            Zeolite is a statically-typed, general-purpose programming language.  description:@@ -36,7 +36,7 @@     .     @     ZEOLITE_PATH=$(zeolite --get-path)-    zeolite -p "$ZEOLITE_PATH" -f -i lib\/util -m HelloDemo example\/hello+    zeolite -p "$ZEOLITE_PATH" -f -I lib\/util -m HelloDemo example\/hello     $ZEOLITE_PATH\/example\/hello\/HelloDemo     @   .@@ -93,6 +93,10 @@                      lib/math/*.0rt,                      lib/math/*.cpp,                      lib/math/*.hpp,+                     lib/testing/.zeolite-module,+                     lib/testing/*.0rp,+                     lib/testing/*.0rt,+                     lib/testing/*.0rx,                      lib/util/.zeolite-module,                      lib/util/*.0rp,                      lib/util/*.0rt,@@ -103,6 +107,8 @@                      tests/*.0rt,                      tests/*.0rx,                      tests/*.sh,+                     tests/bad-path/README.md,+                     tests/bad-path/.zeolite-module,                      tests/check-defs/README.md,                      tests/check-defs/.zeolite-module,                      tests/check-defs/*.0rp,@@ -242,13 +248,14 @@                        ScopedTypeVariables,                        TypeFamilies -  build-depends:       base >= 4.8 && < 4.15,+  build-depends:       base >= 4.9 && < 4.15,                        containers >= 0.3 && < 0.7,                        directory >= 1.2.3 && < 1.4,                        filepath >= 1.0 && < 1.5,                        hashable >= 1.0 && < 1.4,                        mtl >= 1.0 && < 2.3,                        parsec >= 3.0 && < 3.2,+                       parser-combinators >= 0.2 && < 2.0,                        regex-tdfa >= 1.0 && < 1.4,                        time >= 1.0 && < 1.11,                        transformers >= 0.1 && < 0.6,