packages feed

zeolite-lang 0.11.0.0 → 0.12.0.0

raw patch · 26 files changed

+546/−169 lines, 26 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Compilation.CompilerState: ccInheritUsed :: CompilerContext c m s a => a -> a -> m a
+ Compilation.CompilerState: csInheritUsed :: CompilerContext c m s a => a -> CompilerState a m ()
+ Compilation.CompilerState: instance GHC.Classes.Eq c => GHC.Classes.Eq (Compilation.CompilerState.UsedVariable c)
+ Compilation.CompilerState: instance GHC.Classes.Ord c => GHC.Classes.Ord (Compilation.CompilerState.UsedVariable c)
+ Types.Procedure: getOperatorContext :: Operator c -> [c]
+ Types.Procedure: getOperatorName :: Operator c -> FunctionName
+ Types.Procedure: isFunctionOperator :: Operator c -> Bool
- CompilerCxx.Category: compileCategoryDeclaration :: (Show c, CollectErrorsM m) => Bool -> CategoryMap c -> Set Namespace -> AnyCategory c -> m CxxOutput
+ CompilerCxx.Category: compileCategoryDeclaration :: (Ord c, Show c, CollectErrorsM m) => Bool -> CategoryMap c -> Set Namespace -> AnyCategory c -> m CxxOutput
- CompilerCxx.Category: compileConcreteDefinition :: (Show c, CollectErrorsM m) => Bool -> CategoryMap c -> ExprMap c -> Set Namespace -> Maybe [ValueRefine c] -> DefinedCategory c -> m CxxOutput
+ CompilerCxx.Category: compileConcreteDefinition :: (Ord c, Show c, CollectErrorsM m) => Bool -> CategoryMap c -> ExprMap c -> Set Namespace -> Maybe [ValueRefine c] -> DefinedCategory c -> m CxxOutput
- CompilerCxx.Category: compileConcreteTemplate :: (Show c, CollectErrorsM m) => Bool -> CategoryMap c -> CategoryName -> m CxxOutput
+ CompilerCxx.Category: compileConcreteTemplate :: (Ord c, Show c, CollectErrorsM m) => Bool -> CategoryMap c -> CategoryName -> m CxxOutput
- CompilerCxx.Category: compileLanguageModule :: (Show c, CollectErrorsM m) => LanguageModule c -> [PrivateSource c] -> m [CxxOutput]
+ CompilerCxx.Category: compileLanguageModule :: (Ord c, Show c, CollectErrorsM m) => LanguageModule c -> [PrivateSource c] -> m [CxxOutput]
- CompilerCxx.Category: compileModuleMain :: (Show c, CollectErrorsM m) => LanguageModule c -> [PrivateSource c] -> CategoryName -> FunctionName -> m CxxOutput
+ CompilerCxx.Category: compileModuleMain :: (Ord c, Show c, CollectErrorsM m) => LanguageModule c -> [PrivateSource c] -> CategoryName -> FunctionName -> m CxxOutput
- CompilerCxx.Category: compileTestsModule :: (Show c, CollectErrorsM m) => LanguageModule c -> Namespace -> [String] -> [AnyCategory c] -> [DefinedCategory c] -> [TestProcedure c] -> m ([CxxOutput], CxxOutput, [(FunctionName, [c])])
+ CompilerCxx.Category: compileTestsModule :: (Ord c, Show c, CollectErrorsM m) => LanguageModule c -> Namespace -> [String] -> [AnyCategory c] -> [DefinedCategory c] -> [TestProcedure c] -> m ([CxxOutput], CxxOutput, [(FunctionName, [c])])
- CompilerCxx.Procedure: compileExecutableProcedure :: (Show c, CollectErrorsM m) => ScopeContext c -> ScopedFunction c -> ExecutableProcedure c -> m (CompiledData [String], CompiledData [String])
+ CompilerCxx.Procedure: compileExecutableProcedure :: (Ord c, Show c, CollectErrorsM m) => ScopeContext c -> ScopedFunction c -> ExecutableProcedure c -> m (CompiledData [String], CompiledData [String])
- CompilerCxx.Procedure: compileLazyInit :: (Show c, CollectErrorsM m, CompilerContext c m [String] a) => DefinedMember c -> CompilerState a m ()
+ CompilerCxx.Procedure: compileLazyInit :: (Ord c, Show c, CollectErrorsM m, CompilerContext c m [String] a) => DefinedMember c -> CompilerState a m ()
- CompilerCxx.Procedure: compileMainProcedure :: (Show c, CollectErrorsM m) => CategoryMap c -> ExprMap c -> Expression c -> m (CompiledData [String])
+ CompilerCxx.Procedure: compileMainProcedure :: (Ord c, Show c, CollectErrorsM m) => CategoryMap c -> ExprMap c -> Expression c -> m (CompiledData [String])
- CompilerCxx.Procedure: compileRegularInit :: (Show c, CollectErrorsM m, CompilerContext c m [String] a) => DefinedMember c -> CompilerState a m ()
+ CompilerCxx.Procedure: compileRegularInit :: (Ord c, Show c, CollectErrorsM m, CompilerContext c m [String] a) => DefinedMember c -> CompilerState a m ()
- CompilerCxx.Procedure: compileTestProcedure :: (Show c, CollectErrorsM m) => CategoryMap c -> ExprMap c -> TestProcedure c -> m (CompiledData [String])
+ CompilerCxx.Procedure: compileTestProcedure :: (Ord c, Show c, CollectErrorsM m) => CategoryMap c -> ExprMap c -> TestProcedure c -> m (CompiledData [String])
- Types.Procedure: NamedOperator :: String -> Operator c
+ Types.Procedure: NamedOperator :: [c] -> String -> Operator c

Files

ChangeLog.md view
@@ -1,5 +1,60 @@ # Revision history for zeolite-lang +## 0.12.0.0  -- 2020-12-11++### Language++* **[breaking]** Several more fixes for named returns:++  * **[new]** Allows *initialization* of named returns in `if`/`elif`/`while`+    predicates. Although *setting* a named return in a predicate has always been+    allowed, it previously did not count as an initialization for the purposes+    of checking usage in subsequent statements.++  * **[breaking]** Fixes a bug where named returns used in `if`/`elif`/`while`+    predicates inside of `cleanup` blocks were not getting checked for+    initialization. This turns a potential runtime error into a compile-time+    error, which could break buggy code that was never going to be executed.++  * **[fix]** Fixes a bug where a named return with a primitive type was not+    getting set in an explicit `return` statement. This only affected code that+    used primitive named returns inside of a `cleanup` block where the+    corresponding `in` block used an explicit `return` statement.++    ```text+    @type call () -> (Int)+    call () (x) {+      cleanup {+        \ foo(x)     // x was not getting set for this call+      } in return 1  // 1 was still returned from the function as expected+    }+    ```++    This *did not* affect non-primitive types such as `String` and user-defined+    `concrete` and `interface` categories.++* **[breaking]** Updates associativity of infix operators:++  * **[breaking]** Makes infix `Bool` operators `&&` and `||`+    *right-associative*. For example, `x && y && z` used to be parsed as+    `(x && y) && z`, whereas now it is parsed as `x && (y && z)`. This better+    reflects the intuition of side-effects happening in order, with respect to+    short-circuiting. (No other operators currently short-circuit.)++  * **[breaking]** Makes comparison operators (e.g., `<=`) *non-associative*.+    This means that expressions such as `x < y == true` will no longer compile.+    This is because an equivalent-looking expression `true == x < y` might have+    a different interpretation. (Note that order operators such as `<` *are not*+    defined for `Bool`, so something like `x < y < z` would have already failed+    previously.)++  All other infix operators (including infix function calls such as+  ``x `Math.pow` y``) remain *left-associative*.++### Libraries++  * **[new]** Adds `Math.abs` for `Int` absolute value to `lib/math`.+ ## 0.11.0.0  -- 2020-12-09  ### Compiler CLI
lib/file/Category_RawFileReader.cpp view
@@ -94,7 +94,7 @@       &Type_RawFileReader::Call_open,     };     if (label.collection == Functions_RawFileReader) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_RawFileReader / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_RawFileReader[label.function_num])(self, params, args);@@ -124,19 +124,19 @@       &Value_RawFileReader::Call_getFileError,     };     if (label.collection == Functions_BlockReader) {-      if (label.function_num < 0 || label.function_num >= 2) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_BlockReader / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_BlockReader[label.function_num])(self, params, args);     }     if (label.collection == Functions_PersistentResource) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_PersistentResource / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_PersistentResource[label.function_num])(self, params, args);     }     if (label.collection == Functions_RawFileReader) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_RawFileReader / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_RawFileReader[label.function_num])(self, params, args);
lib/file/Category_RawFileWriter.cpp view
@@ -94,7 +94,7 @@       &Type_RawFileWriter::Call_open,     };     if (label.collection == Functions_RawFileWriter) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_RawFileWriter / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_RawFileWriter[label.function_num])(self, params, args);@@ -123,19 +123,19 @@       &Value_RawFileWriter::Call_getFileError,     };     if (label.collection == Functions_BlockWriter) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_BlockWriter / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_BlockWriter[label.function_num])(self, params, args);     }     if (label.collection == Functions_PersistentResource) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_PersistentResource / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_PersistentResource[label.function_num])(self, params, args);     }     if (label.collection == Functions_RawFileWriter) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_RawFileWriter / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_RawFileWriter[label.function_num])(self, params, args);
lib/math/Category_Math.cpp view
@@ -191,6 +191,12 @@     const PrimFloat Var_arg1 = (args.At(0))->AsFloat();     return ReturnTuple(Box_Float(std::trunc(Var_arg1)));   }++  ReturnTuple Call_abs(const S<TypeInstance>& self, const ParamTuple& params, const ValueTuple& args) final {+    TRACE_FUNCTION("Math.abs")+    const PrimInt Var_arg1 = (args.At(0))->AsInt();+    return ReturnTuple(Box_Int(std::abs(Var_arg1)));+  } };  struct Impl_Value_Math : public Value_Math {
lib/math/Source_Math.cpp view
@@ -55,6 +55,7 @@ const TypeFunction& Function_Math_tan = (*new TypeFunction{ 0, 1, 1, "Math", "tan", Functions_Math, 23 }); const TypeFunction& Function_Math_tanh = (*new TypeFunction{ 0, 1, 1, "Math", "tanh", Functions_Math, 24 }); const TypeFunction& Function_Math_trunc = (*new TypeFunction{ 0, 1, 1, "Math", "trunc", Functions_Math, 25 });+const TypeFunction& Function_Math_abs = (*new TypeFunction{ 0, 1, 1, "Math", "abs", Functions_Math, 26 });  std::string Category_Math::CategoryName() const { return "Math"; } @@ -128,9 +129,10 @@     &Type_Math::Call_tan,     &Type_Math::Call_tanh,     &Type_Math::Call_trunc,+    &Type_Math::Call_abs,   };   if (label.collection == Functions_Math) {-    if (label.function_num < 0 || label.function_num >= 26) {+    if (label.function_num < 0 || label.function_num >= sizeof Table_Math / sizeof(CallType)) {       FAIL() << "Bad function call " << label;     }     return (this->*Table_Math[label.function_num])(self, params, args);
lib/math/Source_Math.hpp view
@@ -81,6 +81,7 @@   virtual ReturnTuple Call_tan(const S<TypeInstance>& self, const ParamTuple& params, const ValueTuple& args) = 0;   virtual ReturnTuple Call_tanh(const S<TypeInstance>& self, const ParamTuple& params, const ValueTuple& args) = 0;   virtual ReturnTuple Call_trunc(const S<TypeInstance>& self, const ParamTuple& params, const ValueTuple& args) = 0;+  virtual ReturnTuple Call_abs(const S<TypeInstance>& self, const ParamTuple& params, const ValueTuple& args) = 0;    Category_Math& parent; };
lib/math/math.0rp view
@@ -47,4 +47,6 @@    @type isinf (Float) -> (Bool)   @type isnan (Float) -> (Bool)++  @type abs (Int) -> (Int) }
lib/math/tests.0rt view
@@ -127,3 +127,9 @@     fail("Failed")   } }++unittest abs {+  \ Testing.checkEquals<?>(Math.abs(-10),10)+  \ Testing.checkEquals<?>(Math.abs(10),10)+  \ Testing.checkEquals<?>(Math.abs(0),0)+}
lib/util/Category_Argv.cpp view
@@ -86,7 +86,7 @@       &Type_Argv::Call_global,     };     if (label.collection == Functions_Argv) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_Argv / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_Argv[label.function_num])(self, params, args);@@ -109,7 +109,7 @@       &Value_Argv::Call_subSequence,     };     if (label.collection == Functions_ReadPosition) {-      if (label.function_num < 0 || label.function_num >= 3) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_ReadPosition / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_ReadPosition[label.function_num])(self, params, args);
lib/util/Category_SimpleInput.cpp view
@@ -90,7 +90,7 @@       &Type_SimpleInput::Call_stdin,     };     if (label.collection == Functions_SimpleInput) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_SimpleInput / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_SimpleInput[label.function_num])(self, params, args);@@ -112,7 +112,7 @@       &Value_SimpleInput::Call_readBlock,     };     if (label.collection == Functions_BlockReader) {-      if (label.function_num < 0 || label.function_num >= 2) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_BlockReader / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_BlockReader[label.function_num])(self, params, args);
lib/util/Category_SimpleOutput.cpp view
@@ -100,7 +100,7 @@       &Type_SimpleOutput::Call_stdout,     };     if (label.collection == Functions_SimpleOutput) {-      if (label.function_num < 0 || label.function_num >= 3) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_SimpleOutput / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_SimpleOutput[label.function_num])(self, params, args);@@ -131,13 +131,13 @@       &Value_SimpleOutput::Call_write,     };     if (label.collection == Functions_BufferedWriter) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_BufferedWriter / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_BufferedWriter[label.function_num])(self, params, args);     }     if (label.collection == Functions_Writer) {-      if (label.function_num < 0 || label.function_num >= 1) {+      if (label.function_num < 0 || label.function_num >= sizeof Table_Writer / sizeof(CallType)) {         FAIL() << "Bad function call " << label;       }       return (this->*Table_Writer[label.function_num])(self, params, args);
src/Compilation/CompilerState.hs view
@@ -52,6 +52,7 @@   csGetTypeFunction,   csGetVariable,   csInheritReturns,+  csInheritUsed,   csIsNamedReturns,   csIsUnreachable,   csPrimNamedReturns,@@ -113,6 +114,7 @@   ccClearOutput :: a -> m a   ccUpdateAssigned :: a -> VariableName -> m a   ccAddUsed :: a -> UsedVariable c -> m a+  ccInheritUsed :: a -> a -> m a   ccInheritReturns :: a -> [a] -> m a   ccRegisterReturn :: a -> [c] -> Maybe ExpressionType -> m a   ccPrimNamedReturns :: a -> m [ReturnVariable]@@ -159,7 +161,7 @@     uvContext :: [c],     uvName :: VariableName   }-  deriving (Show)+  deriving (Eq,Ord,Show)  data CleanupBlock c s =   CleanupBlock {@@ -244,6 +246,9 @@  csAddUsed :: CompilerContext c m s a => UsedVariable c -> CompilerState a m () csAddUsed n = fmap (\x -> ccAddUsed x n) get >>= lift >>= put++csInheritUsed :: CompilerContext c m s a => a -> CompilerState a m ()+csInheritUsed c = fmap (\x -> ccInheritUsed x c) get >>= lift >>= put  csInheritReturns :: CompilerContext c m s a => [a] -> CompilerState a m () csInheritReturns xs = fmap (\x -> ccInheritReturns x xs) get >>= lift >>= put
src/Compilation/ProcedureContext.hs view
@@ -398,7 +398,7 @@           pcLoopSetup = pcLoopSetup ctx,           pcCleanupBlocks = pcCleanupBlocks ctx,           pcInCleanup = pcInCleanup ctx,-          pcUsedVars = v:(pcUsedVars ctx),+          pcUsedVars = pcUsedVars ctx ++ [v],           pcExprMap = pcExprMap ctx,           pcReservedMacros = pcReservedMacros ctx,           pcNoTrace = pcNoTrace ctx@@ -444,6 +444,34 @@       combineParallel (ValidateNames ns ts ra1,j1) (ValidateNames _ _ ra2,j2) = (ValidateNames ns ts $ Map.union ra1 ra2,min j1 j2)       combineParallel (r@(ValidatePositions _),j1) (_,j2) = (r,min j1 j2)       combineParallel (_,j1) (r@(ValidatePositions _),j2) = (r,min j1 j2)+  ccInheritUsed ctx ctx2 = 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,+      pcCleanupBlocks = pcCleanupBlocks ctx,+      pcInCleanup = pcInCleanup ctx,+      pcUsedVars = pcUsedVars ctx ++ pcUsedVars ctx2,+      pcExprMap = pcExprMap ctx,+      pcReservedMacros = pcReservedMacros ctx,+      pcNoTrace = pcNoTrace ctx+    }   ccRegisterReturn ctx c vs = do     returns <- check (pcReturns ctx)     return $ ProcedureContext {
src/CompilerCxx/Category.hs view
@@ -99,7 +99,7 @@     psDefine :: [DefinedCategory c]   } -compileLanguageModule :: (Show c, CollectErrorsM m) =>+compileLanguageModule :: (Ord c, Show c, CollectErrorsM m) =>   LanguageModule c -> [PrivateSource c] -> m [CxxOutput] compileLanguageModule (LanguageModule ns0 ns1 ns2 cs0 ps0 ts0 cs1 ps1 ts1 ex ss em) xa = do   checkSupefluous $ Set.toList $ (Set.fromList ex) `Set.difference` ca@@ -205,7 +205,7 @@     streamlinedError n =       compilerErrorM $ "Category " ++ show n ++ " cannot be streamlined because it was not declared external" -compileTestsModule :: (Show c, CollectErrorsM m) =>+compileTestsModule :: (Ord c, Show c, CollectErrorsM m) =>   LanguageModule c -> Namespace -> [String] -> [AnyCategory c] -> [DefinedCategory c] ->   [TestProcedure c] -> m ([CxxOutput],CxxOutput,[(FunctionName,[c])]) compileTestsModule cm ns args cs ds ts = do@@ -219,7 +219,7 @@   (main,fs) <- compileTestMain cm args xs ts   return (xx,main,fs) -compileTestMain :: (Show c, CollectErrorsM m) =>+compileTestMain :: (Ord c, Show c, CollectErrorsM m) =>   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@@ -230,7 +230,7 @@   return (output,tests') where   tm = foldM includeNewTypes defaultCategories [cs0,cs1,ps0,ps1,ts0,ts1,psCategory ts2] -compileModuleMain :: (Show c, CollectErrorsM m) =>+compileModuleMain :: (Ord c, Show c, CollectErrorsM m) =>   LanguageModule c -> [PrivateSource c] -> CategoryName -> FunctionName -> m CxxOutput compileModuleMain (LanguageModule ns0 ns1 ns2 cs0 ps0 _ cs1 ps1 _ _ _ em) xa n f = do   let resolved = filter (\d -> dcName d == n) $ concat $ map psDefine $ filter (not . psTesting) xa@@ -247,7 +247,7 @@       "Multiple matches for main category " ++ show n !!>         mapErrorsM_ (\d -> compilerErrorM $ "Defined at " ++ formatFullContext (dcContext d)) ds -compileCategoryDeclaration :: (Show c, CollectErrorsM m) =>+compileCategoryDeclaration :: (Ord c, Show c, CollectErrorsM m) =>   Bool -> CategoryMap c -> Set.Set Namespace -> AnyCategory c -> m CxxOutput compileCategoryDeclaration testing _ ns t =   return $ CxxOutput (Just $ getCategoryName t)@@ -300,7 +300,7 @@       let allInit = intercalate ", " $ initParent:initPassed       return $ onlyCode $ typeName (getCategoryName t) ++ "(" ++ allArgs ++ ") : " ++ allInit ++ " {}" -compileConcreteTemplate :: (Show c, CollectErrorsM m) =>+compileConcreteTemplate :: (Ord c, Show c, CollectErrorsM m) =>   Bool -> CategoryMap c -> CategoryName -> m CxxOutput compileConcreteTemplate testing ta n = do   (_,t) <- getConcreteCategory ta ([],n)@@ -332,7 +332,7 @@       ]     funcName f = show (sfType f) ++ "." ++ show (sfName f) -compileConcreteStreamlined :: (Show c, CollectErrorsM m) =>+compileConcreteStreamlined :: (Ord c, Show c, CollectErrorsM m) =>   Bool -> CategoryMap c -> CategoryName -> m [CxxOutput] compileConcreteStreamlined testing ta n =  "In streamlined compilation of " ++ show n ??> do   (_,t) <- getConcreteCategory ta ([],n)@@ -354,7 +354,7 @@                       []   return [hxx,cxx] -compileConcreteDefinition :: (Show c, CollectErrorsM m) =>+compileConcreteDefinition :: (Ord c, Show c, CollectErrorsM m) =>   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@@ -413,7 +413,7 @@     ] ++ map (return . snd) (cf ++ tf ++ vf)   commonDefineAll testing t ns rs top bottom ce te fe   where-    disallowTypeMembers :: (Show c, CollectErrorsM m) =>+    disallowTypeMembers :: (Ord c, Show c, CollectErrorsM m) =>       [DefinedMember c] -> m ()     disallowTypeMembers tm =       collectAllM_ $ flip map tm@@ -622,9 +622,9 @@     ["  static const CallType " ++ tableName n2 ++ "[] = {"] ++     map (\f -> "    &" ++ name f ++ ",") (Set.toList $ Set.fromList $ map sfName fs2) ++     ["  };"]-  dispatch (n2,fs2) = [+  dispatch (n2,_) = [       "  if (label.collection == " ++ collectionName n2 ++ ") {",-      "    if (label.function_num < 0 || label.function_num >= " ++ show (length fs2) ++ ") {",+      "    if (label.function_num < 0 || label.function_num >= sizeof " ++ tableName n2 ++ " / sizeof(CallType)) {",       "      FAIL() << \"Bad function call \" << label;",       "    }",       "    return (this->*" ++ tableName n2 ++ "[label.function_num])(" ++ args ++ ");",@@ -831,7 +831,7 @@       depIncludes req2 = map (\i -> "#include \"" ++ headerFilename i ++ "\"") $                            Set.toList req2 -createMainFile :: (Show c, CollectErrorsM m) =>+createMainFile :: (Ord c, Show c, CollectErrorsM 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 <- compileMainProcedure tm em expr@@ -843,7 +843,7 @@     expr = Expression [] (TypeCall [] mainType funcCall) []     argv = onlyCode "ProgramArgv program_argv(argc, argv);" -createTestFile :: (Show c, CollectErrorsM m) =>+createTestFile :: (Ord c, Show c, CollectErrorsM m) =>   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
src/CompilerCxx/Procedure.hs view
@@ -37,7 +37,7 @@ import Control.Monad (when) import Control.Monad.Trans.State (execStateT,get,put,runStateT) import Control.Monad.Trans (lift)-import Data.List (intercalate)+import Data.List (intercalate,nub) import qualified Data.Map as Map import qualified Data.Set as Set @@ -61,7 +61,7 @@ import Types.Variance  -compileExecutableProcedure :: (Show c, CollectErrorsM m) =>+compileExecutableProcedure :: (Ord c, Show c, CollectErrorsM m) =>   ScopeContext c -> ScopedFunction c -> ExecutableProcedure c ->   m (CompiledData [String],CompiledData [String]) compileExecutableProcedure ctx ff@(ScopedFunction _ _ _ s as1 rs1 ps1 _ _)@@ -143,16 +143,15 @@         variableProxyType t2 ++ " " ++ variableName (ovName n2) ++         " = " ++ writeStoredVariable t2 (UnwrappedSingle $ "returns.At(" ++ show i ++ ")") ++ ";" -compileCondition :: (Show c, CollectErrorsM m,+compileCondition :: (Ord c, Show c, CollectErrorsM m,                      CompilerContext c m [String] a) =>-  a -> [c] -> Expression c -> CompilerState a m String+  a -> [c] -> Expression c -> CompilerState a m (String,a) compileCondition ctx c e = do   (e',ctx') <- resetBackgroundM $ lift $ runStateT compile ctx-  lift (ccGetRequired ctx') >>= csAddRequired   noTrace <- csGetNoTrace   if noTrace-     then return e'-     else return $ predTraceContext c ++ e'+     then return (e',ctx')+     else return (predTraceContext c ++ e',ctx')   where     compile = "In condition at " ++ formatFullContext c ??> do       (ts,e') <- compileExpression e@@ -161,11 +160,11 @@       where         checkCondition (Positional [t]) | t == boolRequiredValue = return ()         checkCondition (Positional ts) =-          compilerErrorM $ "Conditionals must have exactly one Bool return but found {" ++-                           intercalate "," (map show ts) ++ "}"+          compilerErrorM $ "Expected exactly one Bool value but got " +++                           intercalate ", " (map show ts)  -- Returns the state so that returns can be properly checked for if/elif/else.-compileProcedure :: (Show c, CollectErrorsM m,+compileProcedure :: (Ord c, Show c, CollectErrorsM m,                      CompilerContext c m [String] a) =>   a -> Procedure c -> CompilerState a m a compileProcedure ctx (Procedure _ ss) = do@@ -181,14 +180,14 @@            s' <- resetBackgroundM $ compileStatement s            return s' -maybeSetTrace :: (Show c, CollectErrorsM m,+maybeSetTrace :: (Ord c, Show c, CollectErrorsM m,                   CompilerContext c m [String] a) =>   [c] -> CompilerState a m () maybeSetTrace c = do   noTrace <- csGetNoTrace   when (not noTrace) $ csWrite $ setTraceContext c -compileStatement :: (Show c, CollectErrorsM m,+compileStatement :: (Ord c, Show c, CollectErrorsM m,                      CompilerContext c m [String] a) =>   Statement c -> CompilerState a m () compileStatement (EmptyReturn c) = do@@ -306,7 +305,7 @@ compileStatement (NoValueExpression _ v) = compileVoidExpression v compileStatement (RawCodeLine s) = csWrite [s] -compileRegularInit :: (Show c, CollectErrorsM m,+compileRegularInit :: (Ord c, Show c, CollectErrorsM m,                        CompilerContext c m [String] a) =>   DefinedMember c -> CompilerState a m () compileRegularInit (DefinedMember _ _ _ _ Nothing) = return ()@@ -315,7 +314,7 @@   let assign = Assignment c2 (Positional [ExistingVariable (InputValue c2 n2)]) e   compileStatement assign -compileLazyInit :: (Show c, CollectErrorsM m,+compileLazyInit :: (Ord c, Show c, CollectErrorsM m,                    CompilerContext c m [String] a) =>   DefinedMember c -> CompilerState a m () compileLazyInit (DefinedMember _ _ _ _ Nothing) = return ()@@ -330,7 +329,7 @@     "In initialization of " ++ show n ++ " at " ++ formatFullContext c   csWrite [variableName n ++ "([this]() { return " ++ writeStoredVariable t1 e' ++ "; })"] -compileVoidExpression :: (Show c, CollectErrorsM m,+compileVoidExpression :: (Ord c, Show c, CollectErrorsM m,                          CompilerContext c m [String] a) =>   VoidExpression c -> CompilerState a m () compileVoidExpression (Conditional ie) = compileIfElifElse ie@@ -344,64 +343,58 @@   autoInlineOutput ctx   csWrite ["}"] -compileIfElifElse :: (Show c, CollectErrorsM m,+compileIfElifElse :: (Ord c, Show c, CollectErrorsM m,                       CompilerContext c m [String] a) =>   IfElifElse c -> CompilerState a m () compileIfElifElse (IfStatement c e p es) = do   ctx0 <- getCleanContext-  e' <- compileCondition ctx0 c e-  ctx <- compileProcedure ctx0 p-  (lift $ ccGetRequired ctx) >>= csAddRequired-  csWrite ["if (" ++ e' ++ ") {"]-  getAndIndentOutput ctx >>= csWrite-  csWrite ["}"]-  cs <- unwind es-  csInheritReturns (ctx:cs)+  cs <- commonIf ctx0 "if" c e p es+  csInheritReturns cs   where-    unwind (IfStatement c2 e2 p2 es2) = do-      ctx0 <- getCleanContext-      e2' <- compileCondition ctx0 c2 e2-      ctx <- compileProcedure ctx0 p2-      (lift $ ccGetRequired ctx) >>= csAddRequired-      csWrite ["else if (" ++ e2' ++ ") {"]-      getAndIndentOutput ctx >>= csWrite-      csWrite ["}"]-      cs <- unwind es2-      return $ ctx:cs-    unwind (ElseStatement _ p2) = do-      ctx0 <- getCleanContext+    unwind ctx0 (IfStatement c2 e2 p2 es2) = commonIf ctx0 "else if" c2 e2 p2 es2+    unwind ctx0 (ElseStatement _ p2) = do       ctx <- compileProcedure ctx0 p2-      (lift $ ccGetRequired ctx) >>= csAddRequired+      inheritRequired ctx       csWrite ["else {"]       getAndIndentOutput ctx >>= csWrite       csWrite ["}"]       return [ctx]-    unwind TerminateConditional = fmap (:[]) get+    unwind ctx0 TerminateConditional = return [ctx0]+    commonIf ctx0 s c2 e2 p2 es2 = do+      (e2',ctx1) <- compileCondition ctx0 c2 e2+      ctx <- compileProcedure ctx1 p2+      inheritRequired ctx+      csWrite [s ++ " (" ++ e2' ++ ") {"]+      getAndIndentOutput ctx >>= csWrite+      csWrite ["}"]+      cs <- unwind ctx1 es2+      return $ ctx:cs compileIfElifElse _ = undefined -compileWhileLoop :: (Show c, CollectErrorsM m,+compileWhileLoop :: (Ord c, Show c, CollectErrorsM m,                      CompilerContext c m [String] a) =>   WhileLoop c -> CompilerState a m () compileWhileLoop (WhileLoop c e p u) = do   ctx0 <- getCleanContext-  e' <- compileCondition ctx0 c e+  (e',ctx1) <- compileCondition ctx0 c e+  csInheritReturns [ctx1]   ctx0' <- case u of                 Just p2 -> do-                  ctx1 <- lift $ ccStartLoop ctx0 (LoopSetup [])-                  ctx2 <- compileProcedure ctx1 p2-                  (lift $ ccGetRequired ctx2) >>= csAddRequired-                  p2' <- getAndIndentOutput ctx2-                  lift $ ccStartLoop ctx0 (LoopSetup p2')-                _ -> lift $ ccStartLoop ctx0 (LoopSetup [])+                  ctx2 <- lift $ ccStartLoop ctx1 (LoopSetup [])+                  ctx3 <- compileProcedure ctx2 p2+                  inheritRequired ctx3+                  p2' <- getAndIndentOutput ctx3+                  lift $ ccStartLoop ctx1 (LoopSetup p2')+                _ -> lift $ ccStartLoop ctx1 (LoopSetup [])   (LoopSetup u') <- lift $ ccGetLoop ctx0'   ctx <- compileProcedure ctx0' p-  (lift $ ccGetRequired ctx) >>= csAddRequired+  inheritRequired ctx   csWrite ["while (" ++ e' ++ ") {"]   getAndIndentOutput ctx >>= csWrite   csWrite $ ["{"] ++ u' ++ ["}"]   csWrite ["}"] -compileScopedBlock :: (Show c, CollectErrorsM m,+compileScopedBlock :: (Ord c, Show c, CollectErrorsM m,                        CompilerContext c m [String] a) =>   ScopedBlock c -> CompilerState a m () compileScopedBlock s@(ScopedBlock _ _ _ c2 _) = do@@ -466,7 +459,7 @@     rewriteScoped (ScopedBlock _ p cl _ s2) =       ([],p,cl,s2) -compileExpression :: (Show c, CollectErrorsM m,+compileExpression :: (Ord c, Show c, CollectErrorsM m,                       CompilerContext c m [String] a) =>   Expression c -> CompilerState a m (ExpressionType,ExprValue) compileExpression = compile where@@ -511,11 +504,11 @@     compile (Expression c (ParensExpression c2 e0) [ValueCall c (FunctionCall c fn ps (Positional [e]))])   compile (UnaryExpression c (FunctionOperator _ (FunctionSpec c2 UnqualifiedFunction fn ps)) e) =     compile (Expression c (UnqualifiedCall c2 (FunctionCall c fn ps (Positional [e]))) [])-  compile (UnaryExpression c (NamedOperator "-") (Literal (IntegerLiteral _ _ l))) =+  compile (UnaryExpression _ (NamedOperator c "-") (Literal (IntegerLiteral _ _ l))) =     compile (Literal (IntegerLiteral c False (-l)))-  compile (UnaryExpression c (NamedOperator "-") (Literal (DecimalLiteral _ l e))) =+  compile (UnaryExpression _ (NamedOperator c "-") (Literal (DecimalLiteral _ l e))) =     compile (Literal (DecimalLiteral c (-l) e))-  compile (UnaryExpression c (NamedOperator o) e) = do+  compile (UnaryExpression _ (NamedOperator c o) e) = do     (Positional ts,e') <- compileExpression e     t' <- requireSingle c ts     doUnary t' e'@@ -577,7 +570,7 @@     compile (Expression c (ParensExpression c2 e0) [ValueCall c (FunctionCall c fn ps (Positional [e1,e2]))])   compile (InfixExpression c e1 (FunctionOperator _ (FunctionSpec c2 UnqualifiedFunction fn ps)) e2) =     compile (Expression c (UnqualifiedCall c2 (FunctionCall c fn ps (Positional [e1,e2]))) [])-  compile (InfixExpression c e1 (NamedOperator o) e2) = do+  compile (InfixExpression _ e1 (NamedOperator c o) e2) = do     e1' <- compileExpression e1     e2' <- if o `Set.member` logical               then isolateExpression e2 -- Ignore named-return assignments.@@ -586,7 +579,8 @@   isolateExpression e = do     ctx <- getCleanContext     (e',ctx') <- lift $ runStateT (compileExpression e) ctx-    (lift $ ccGetRequired ctx') >>= csAddRequired+    inheritRequired ctx'+    csInheritUsed ctx'     return e'   arithmetic1 = Set.fromList ["*","/"]   arithmetic2 = Set.fromList ["%"]@@ -604,7 +598,7 @@       bind t1 t2         | t1 /= t2 =           compilerErrorM $ "Cannot " ++ show o ++ " " ++ show t1 ++ " and " ++-                                 show t2 ++ formatFullContextBrace c+                           show t2 ++ formatFullContextBrace c         | o `Set.member` comparison && t1 == intRequiredValue = do           return (Positional [boolRequiredValue],glueInfix PrimInt PrimBool e1 o e2)         | o `Set.member` comparison && t1 == floatRequiredValue = do@@ -658,7 +652,7 @@     compilerErrorM $ "Function call requires 1 return but found but found {" ++                             intercalate "," (map show ts) ++ "}" ++ formatFullContextBrace c2 -lookupValueFunction :: (Show c, CollectErrorsM m,+lookupValueFunction :: (Ord c, Show c, CollectErrorsM m,                         CompilerContext c m [String] a) =>   ValueType -> FunctionCall c -> CompilerState a m (ScopedFunction c) lookupValueFunction (ValueType WeakValue t) (FunctionCall c _ _ _) =@@ -670,7 +664,7 @@ lookupValueFunction (ValueType RequiredValue t) (FunctionCall c n _ _) =   csGetTypeFunction c (Just t) n -compileExpressionStart :: (Show c, CollectErrorsM m,+compileExpressionStart :: (Ord c, Show c, CollectErrorsM m,                            CompilerContext c m [String] a) =>   ExpressionStart c -> CompilerState a m (ExpressionType,ExprValue) compileExpressionStart (NamedVariable (OutputValue c n)) = do@@ -813,13 +807,13 @@   return (Positional [t0],readStoredVariable lazy t0 $ "(" ++ scoped ++ variableName n ++                                                      " = " ++ writeStoredVariable t0 e' ++ ")") -disallowInferred :: (Show c, CollectErrorsM m) => Positional (InstanceOrInferred c) -> m [GeneralInstance]+disallowInferred :: (Ord c, Show c, CollectErrorsM m) => Positional (InstanceOrInferred c) -> m [GeneralInstance] disallowInferred = mapErrorsM disallow . pValues where   disallow (AssignedInstance _ t) = return t   disallow (InferredInstance c) =     compilerErrorM $ "Type inference is not allowed in reduce calls" ++ formatFullContextBrace c -compileFunctionCall :: (Show c, CollectErrorsM m,+compileFunctionCall :: (Ord c, Show c, CollectErrorsM m,                         CompilerContext c m [String] a) =>   Maybe String -> ScopedFunction c -> FunctionCall c ->   CompilerState a m (ExpressionType,ExprValue)@@ -876,7 +870,7 @@     checkArg r fa t0 (i,t1) = do       checkValueAssignment r fa t1 t0 <?? "In argument " ++ show i ++ " to " ++ show (sfName f) -guessParamsFromArgs :: (Show c, CollectErrorsM m, TypeResolver r) =>+guessParamsFromArgs :: (Ord c, Show c, CollectErrorsM m, TypeResolver r) =>   r -> ParamFilters -> ScopedFunction c -> Positional (InstanceOrInferred c) ->   Positional ValueType -> m (Positional GeneralInstance) guessParamsFromArgs r fa f ps ts = do@@ -895,7 +889,7 @@     toInstance p1 (AssignedInstance _ t) = return (p1,t)     toInstance p1 (InferredInstance _)   = return (p1,singleType $ JustInferredType p1) -compileMainProcedure :: (Show c, CollectErrorsM m) =>+compileMainProcedure :: (Ord c, Show c, CollectErrorsM m) =>   CategoryMap c -> ExprMap c -> Expression c -> m (CompiledData [String]) compileMainProcedure tm em e = do   ctx <- getMainContext tm em@@ -905,7 +899,7 @@       ctx0 <- getCleanContext       compileProcedure ctx0 procedure >>= put -compileTestProcedure :: (Show c, CollectErrorsM m) =>+compileTestProcedure :: (Ord c, Show c, CollectErrorsM m) =>   CategoryMap c -> ExprMap c -> TestProcedure c -> m (CompiledData [String]) compileTestProcedure tm em (TestProcedure c n p) = do   ctx <- getMainContext tm em@@ -1009,7 +1003,7 @@     ps' <- sequence ps     return $ "(L_get<S<const " ++ typeBase ++ ">>(" ++ intercalate "," ps' ++ "))" -doImplicitReturn :: (CollectErrorsM m, Show c, CompilerContext c m [String] a) =>+doImplicitReturn :: (CollectErrorsM m, Ord c, Show c, CompilerContext c m [String] a) =>   [c] -> CompilerState a m () doImplicitReturn c = do   named <- csIsNamedReturns@@ -1021,26 +1015,24 @@   if not named      then csWrite ["return ReturnTuple(0);"]      else do-       vars <- csPrimNamedReturns-       sequence_ $ map (csWrite . (:[]) . assign) vars+       getPrimNamedReturns        csWrite ["return returns;"]   where-    assign (ReturnVariable i n t) =-      "returns.At(" ++ show i ++ ") = " ++ useAsUnwrapped (readStoredVariable False t $ variableName n) ++ ";"  autoPositionalCleanup :: (CollectErrorsM m, CompilerContext c m [String] a) =>   [c] -> ExprValue -> CompilerState a m () autoPositionalCleanup c e = do+  named <- csIsNamedReturns   (CleanupBlock ss _ _ req) <- csGetCleanup JumpReturn   csAddRequired req   csSetJumpType c JumpReturn   if null ss      then csWrite ["return " ++ useAsReturns e ++ ";"]      else do-       named <- csIsNamedReturns        if named           then do             csWrite ["returns = " ++ useAsReturns e ++ ";"]+            setPrimNamedReturns             csWrite ss             csWrite ["return returns;"]           else do@@ -1048,11 +1040,29 @@             csWrite ss             csWrite ["return returns;","}"] -autoInsertCleanup :: (Show c, CollectErrorsM m, CompilerContext c m [String] a) =>+setPrimNamedReturns ::  (CollectErrorsM m, CompilerContext c m [String] a) =>+  CompilerState a m ()+setPrimNamedReturns = do+  vars <- csPrimNamedReturns+  sequence_ $ map (csWrite . (:[]) . assign) vars where+    assign (ReturnVariable i n t) =+      variableName n ++ " = " ++ writeStoredVariable t (position i) ++ ";"+    position i = WrappedSingle $ "returns.At(" ++ show i ++ ")"++getPrimNamedReturns ::  (CollectErrorsM m, CompilerContext c m [String] a) =>+  CompilerState a m ()+getPrimNamedReturns = do+  vars <- csPrimNamedReturns+  sequence_ $ map (csWrite . (:[]) . assign) vars where+    assign (ReturnVariable i n t) =+      "returns.At(" ++ show i ++ ") = " ++ useAsUnwrapped (readStoredVariable False t $ variableName n) ++ ";"++autoInsertCleanup :: (Ord c, Show c, CollectErrorsM m, CompilerContext c m [String] a) =>   [c] -> JumpType -> a -> CompilerState a m () autoInsertCleanup c j ctx = do   (CleanupBlock ss vs jump req) <- lift $ ccGetCleanup ctx j-  lift (ccCheckVariableInit ctx vs) <?? "In inlining of cleanup block after statement at " ++ formatFullContext c+  lift (ccCheckVariableInit ctx $ nub vs) <??+    "In inlining of cleanup block after statement at " ++ formatFullContext c   let vs2 = map (\(UsedVariable c0 v) -> UsedVariable (c ++ c0) v) vs   -- This is needed in case a cleanup is inlined within another cleanup, e.g.,   -- e.g., if the latter has a break statement.@@ -1061,14 +1071,18 @@   csAddRequired req   csSetJumpType c jump -autoInlineOutput :: (Show c, CollectErrorsM m, CompilerContext c m [String] a) =>+inheritRequired :: (CollectErrorsM m, CompilerContext c m [String] a) =>   a -> CompilerState a m ()+inheritRequired ctx = lift (ccGetRequired ctx) >>= csAddRequired++autoInlineOutput :: (Ord c, Show c, CollectErrorsM m, CompilerContext c m [String] a) =>+  a -> CompilerState a m () autoInlineOutput ctx = do-  (lift $ ccGetRequired ctx) >>= csAddRequired+  inheritRequired ctx   getAndIndentOutput ctx >>= csWrite   csInheritReturns [ctx] -getAndIndentOutput :: (Show c, CollectErrorsM m, CompilerContext c m [String] a) =>+getAndIndentOutput :: (Ord c, Show c, CollectErrorsM m, CompilerContext c m [String] a) =>   a -> CompilerState a m [String] getAndIndentOutput ctx = fmap indentCode (lift $ ccGetOutput ctx) 
src/Parser/DefinedCategory.hs view
@@ -21,7 +21,6 @@ module Parser.DefinedCategory ( ) where -import Control.Monad (when) import Prelude hiding (pi)  import Base.CompilerError@@ -98,10 +97,9 @@   return (ms,ps2,fs2) where     singleFunction = labeled "function" $ do       f <- parseScopedFunction parseScope (return n)+      lookAhead (sepAfter $ string_ $ show (sfName f)) <|>+        (compilerErrorM $ "expected definition of function " ++ show (sfName f))       p <- labeled ("definition of function " ++ show (sfName f)) $ sourceParser-      when (sfName f /= epName p) $-        compilerErrorM $ "expecting definition of function " ++ show (sfName f) ++-                         " but got definition of " ++ show (epName p)       return (f,p)     catchUnscopedType = labeled "" $ do       _ <- try sourceParser :: TextParser ValueType
src/Parser/Procedure.hs view
@@ -22,6 +22,7 @@ module Parser.Procedure ( ) where +import Control.Monad (when) import qualified Data.Set as Set  import Base.CompilerError@@ -251,10 +252,13 @@       p <- between (sepAfter $ string_ "{") (sepAfter $ string_ "}") sourceParser       return $ NoValueExpression [c] (Unconditional p) -unaryOperator :: TextParser (Operator c)-unaryOperator = op >>= return . NamedOperator where-  op = labeled "unary operator" $ foldr (<|>) empty $ map (try . operator) ops-  ops = logicalUnary ++ arithUnary ++ bitwiseUnary+unaryOperator :: TextParser (Operator SourceContext)+unaryOperator = do+  c <- getSourceContext+  o <- op+  return $ NamedOperator [c] o where+    op = labeled "unary operator" $ foldr (<|>) empty $ map (try . operator) ops+    ops = logicalUnary ++ arithUnary ++ bitwiseUnary  logicalUnary :: [String] logicalUnary = ["!"]@@ -265,10 +269,13 @@ bitwiseUnary :: [String] bitwiseUnary = ["~"] -infixOperator :: TextParser (Operator c)-infixOperator = op >>= return . NamedOperator where-  op = labeled "binary operator" $ foldr (<|>) empty $ map (try . operator) ops-  ops = compareInfix ++ logicalInfix ++ addInfix ++ subInfix ++ multInfix ++ bitwiseInfix ++ bitshiftInfix+infixOperator :: TextParser (Operator SourceContext)+infixOperator =  do+  c <- getSourceContext+  o <- op+  return $ NamedOperator [c] o where+    op = labeled "binary operator" $ foldr (<|>) empty $ map (try . operator) ops+    ops = compareInfix ++ logicalInfix ++ addInfix ++ subInfix ++ multInfix ++ divInfix ++ bitwiseInfix ++ bitshiftInfix  compareInfix :: [String] compareInfix = ["==","!=","<","<=",">",">="]@@ -283,24 +290,26 @@ subInfix = ["-"]  multInfix :: [String]-multInfix = ["*","/","%"]+multInfix = ["*"] +divInfix :: [String]+divInfix = ["/","%"]+ bitwiseInfix :: [String] bitwiseInfix = ["&","|","^"]  bitshiftInfix :: [String] bitshiftInfix = [">>","<<"] -infixBefore :: Operator c -> Operator c -> Bool-infixBefore o1 o2 = (infixOrder o1 :: Int) <= (infixOrder o2 :: Int) where-  infixOrder (NamedOperator o)-    -- TODO: Don't hard-code this.-    | o `Set.member` Set.fromList (multInfix ++ bitshiftInfix) = 1-    | o `Set.member` Set.fromList (addInfix ++ subInfix ++ bitwiseInfix) = 2-    | o `Set.member` Set.fromList compareInfix = 4-    | o `Set.member` Set.fromList logicalInfix = 5-  infixOrder _ = 3+leftAssocInfix :: [String]+leftAssocInfix = addInfix ++ subInfix ++ multInfix ++ divInfix ++ bitwiseInfix ++ bitshiftInfix +rightAssocInfix :: [String]+rightAssocInfix = logicalInfix++nonAssocInfix :: [String]+nonAssocInfix = compareInfix+ functionOperator :: TextParser (Operator SourceContext) functionOperator = do   c <- getSourceContext@@ -309,6 +318,48 @@   infixFuncEnd   return $ FunctionOperator [c] q +inOperatorSet :: Operator c -> [String] -> Bool+inOperatorSet (NamedOperator _ o) ss = o `Set.member` Set.fromList ss+inOperatorSet _                   _  = False++bothInOperatorSet :: Operator c -> Operator c -> [String] -> Bool+bothInOperatorSet o1 o2 ss = o1 `inOperatorSet` ss && o2 `inOperatorSet` ss++infixPrecedence :: Operator c -> Int+infixPrecedence o+  -- TODO: Don't hard-code this.+  | o `inOperatorSet` (multInfix ++ divInfix ++ bitshiftInfix) = 1+  | o `inOperatorSet` (addInfix ++ subInfix ++ bitwiseInfix) = 2+  | o `inOperatorSet` compareInfix = 4+  | o `inOperatorSet` logicalInfix = 5+infixPrecedence _ = 3++infixBefore :: (Show c, ErrorContextM m) => Operator c -> Operator c -> m Bool+infixBefore o1 o2 = do+  let prec1 = infixPrecedence o1+  let prec2 = infixPrecedence o2+  if prec1 /= prec2+     then return $ prec1 < prec2+     -- NOTE: Ambiguity is checked separately so that the error occurs where the+     -- second operator is parsed, rather than at the end of the expression.+     else if bothInOperatorSet o1 o2 rightAssocInfix+             then return False  -- Logical operators are right-associative.+             else return True   -- Default is left-associative.+  where++checkAmbiguous :: (Show c, ErrorContextM m) => Operator c -> Operator c -> m ()+checkAmbiguous o1 o2 = checked where+  formatOperator o = show (getOperatorName o) +++                     " (" ++ formatFullContext (getOperatorContext o) ++ ")"+  checked+    | infixPrecedence o1 /= infixPrecedence o2 = return ()+    | bothInOperatorSet o1 o2 leftAssocInfix  = return ()+    | bothInOperatorSet o1 o2 rightAssocInfix = return ()+    | isFunctionOperator o1 && isFunctionOperator o2 = return ()+    | otherwise =+        compilerErrorM $ "the order of operators " ++ formatOperator o1 +++                         " and " ++ formatOperator o2 ++ " is ambiguous"+ instance ParseFromSource (Expression SourceContext) where   sourceParser = do     e <- notInfix@@ -318,18 +369,21 @@       asInfix es os = do         c <- getSourceContext         o <- infixOperator <|> functionOperator+        when (not $ null os) $ checkAmbiguous (snd $ last os) o         e2 <- notInfix         let es' = es ++ [e2]         let os' = os ++ [([c],o)]-        asInfix es' os' <|> return (infixToTree [] es' os')-      infixToTree [(e1,c1,o1)] [e2] [] = InfixExpression c1 e1 o1 e2+        asInfix es' os' <|> (infixToTree [] es' os')+      infixToTree [(e1,c1,o1)] [e2] [] = return $ InfixExpression c1 e1 o1 e2       infixToTree [] (e1:es) ((c1,o1):os) = infixToTree [(e1,c1,o1)] es os       infixToTree ((e1,c1,o1):ss) [e2] [] = let e2' = InfixExpression c1 e1 o1 e2 in                                                 infixToTree ss [e2'] []-      infixToTree ((e1,c1,o1):ss) (e2:es) ((c2,o2):os)-        | o1 `infixBefore` o2 = let e1' = InfixExpression c1 e1 o1 e2 in-                                    infixToTree ss (e1':es) ((c2,o2):os)-        | otherwise = infixToTree ((e2,c2,o2):(e1,c1,o1):ss) es os+      infixToTree ((e1,c1,o1):ss) (e2:es) ((c2,o2):os) = do+        before <- o1 `infixBefore` o2+        if before+           then let e1' = InfixExpression c1 e1 o1 e2 in+                          infixToTree ss (e1':es) ((c2,o2):os)+           else infixToTree ((e2,c2,o2):(e1,c1,o1):ss) es os       infixToTree _ _ _ = undefined       literal = do         l <- sourceParser
src/Test/Procedure.hs view
@@ -208,6 +208,13 @@     checkShortParseFail "x <- 'xx'",     checkShortParseSuccess "x <- \"'xx\"", +    checkShortParseFail "_ <- 1 < 2 < 3",+    checkShortParseSuccess "_ <- 1 << 2 >> 3",+    checkShortParseSuccess "_ <- 1 - 2 - 3",+    checkShortParseSuccess "_ <- 1 - 2 / 3",+    checkShortParseSuccess "_ <- 1 / 2 - 3",+    checkShortParseSuccess "_ <- x < y || z > w",+     checkParsesAs "'\"'"                   (\e -> case e of                               (Literal (CharLiteral _ '"')) -> True@@ -218,18 +225,18 @@                               (InfixExpression _                                 (InfixExpression _                                   (InfixExpression _-                                    (InfixExpression _-                                      (Literal (IntegerLiteral _ False 1)) (NamedOperator "+")-                                      (Literal (IntegerLiteral _ False 2))) (NamedOperator "<")-                                    (Literal (IntegerLiteral _ False 4))) (NamedOperator "&&")+                                    (Literal (IntegerLiteral _ False 1)) (NamedOperator _ "+")+                                    (Literal (IntegerLiteral _ False 2))) (NamedOperator _ "<")+                                  (Literal (IntegerLiteral _ False 4))) (NamedOperator _ "&&")+                                (InfixExpression _                                   (InfixExpression _-                                    (Literal (IntegerLiteral _ False 3)) (NamedOperator ">=")+                                    (Literal (IntegerLiteral _ False 3)) (NamedOperator _ ">=")                                     (InfixExpression _                                       (InfixExpression _-                                        (Literal (IntegerLiteral _ False 1)) (NamedOperator "*")-                                        (Literal (IntegerLiteral _ False 2))) (NamedOperator "+")-                                      (Literal (IntegerLiteral _ False 1))))) (NamedOperator "||")-                                (Literal (BoolLiteral _ True))) -> True+                                        (Literal (IntegerLiteral _ False 1)) (NamedOperator _ "*")+                                        (Literal (IntegerLiteral _ False 2))) (NamedOperator _ "+")+                                      (Literal (IntegerLiteral _ False 1)))) (NamedOperator _ "||")+                                  (Literal (BoolLiteral _ True)))) -> True                               _ -> False),      -- This expression isn't really valid, but it ensures that the first ! is@@ -238,11 +245,11 @@                   (\e -> case e of                               (InfixExpression _                                 (InfixExpression _-                                  (UnaryExpression _ (NamedOperator "!")-                                    (Expression _ (NamedVariable (OutputValue _ (VariableName "x"))) [])) (NamedOperator "*")-                                  (UnaryExpression _ (NamedOperator "!")-                                    (Expression _ (NamedVariable (OutputValue _ (VariableName "y"))) []))) (NamedOperator "+")-                                (UnaryExpression _ (NamedOperator "!")+                                  (UnaryExpression _ (NamedOperator _ "!")+                                    (Expression _ (NamedVariable (OutputValue _ (VariableName "x"))) [])) (NamedOperator _ "*")+                                  (UnaryExpression _ (NamedOperator _ "!")+                                    (Expression _ (NamedVariable (OutputValue _ (VariableName "y"))) []))) (NamedOperator _ "+")+                                (UnaryExpression _ (NamedOperator _ "!")                                   (Expression _ (NamedVariable (OutputValue _ (VariableName "z"))) []))) -> True                               _ -> False), 
src/Types/Procedure.hs view
@@ -44,8 +44,11 @@   WhileLoop(..),   assignableName,   getExpressionContext,+  getOperatorContext,+  getOperatorName,   getStatementContext,   isDiscardedInput,+  isFunctionOperator,   isLiteralCategory,   isRawCodeLine,   isUnnamedReturns,@@ -238,9 +241,21 @@   deriving (Show)  data Operator c =-  NamedOperator String |+  NamedOperator [c] String |   FunctionOperator [c] (FunctionSpec c)   deriving (Show)++getOperatorContext :: Operator c -> [c]+getOperatorContext (NamedOperator c _)    = c+getOperatorContext (FunctionOperator c _) = c++isFunctionOperator :: Operator c -> Bool+isFunctionOperator (FunctionOperator _ _) = True+isFunctionOperator _                      = False++getOperatorName :: Operator c -> FunctionName+getOperatorName (NamedOperator _ n)                         = FunctionName n+getOperatorName (FunctionOperator _ (FunctionSpec _ _ n _)) = n  getExpressionContext :: Expression c -> [c] getExpressionContext (Expression c _ _)        = c
tests/cli-tests.sh view
@@ -279,8 +279,16 @@   test_example_hello() {+  local binary="$ZEOLITE_PATH/example/hello/HelloDemo"+  local name='Cli Tests'+  rm -f "$binary"   do_zeolite -p "$ZEOLITE_PATH" -I lib/util -m HelloDemo example/hello -f-  do_zeolite -p "$ZEOLITE_PATH" -t example/hello+  local output=$(echo "$name" | "$binary" 2>&1)+  if ! echo "$output" | egrep -q "\"$name\""; then+    show_message "Expected \"$name\" in output:"+    echo "$output" 1>&2+    return 1+  fi }  
tests/conditionals.0rt view
@@ -57,8 +57,7 @@   testcase "assign if/elif condition" {-  error-  require "value.+initialized"+  compiles }  define Value {@@ -168,6 +167,47 @@       value <- empty     } elif (false) {       value <- empty+    }+  }+}++concrete Value {}+++testcase "return set in predicate for subsequent blocks" {+  compiles+}++define Value {+  @value process () -> (Int)+  process () (x) {+    if (false) {+      x <- 1+    } elif ((x <- 1) > 0) {+      fail(x)+    } else {+    }+  }+}++concrete Value {}++++testcase "return in set in predicates is conditional" {+  error+  require "implicit return"+  require "x.+initialized"+}++define Value {+  @value process () -> (Int)+  process () (x) {+    if (false) {+    } elif ((x <- 1) > 0) {+      fail(x)+    } else {+      fail(x)     }   } }
tests/infix-functions.0rt view
@@ -156,3 +156,36 @@     return x + y   } }+++testcase "infix function associativity" {+  success+}++unittest test {+  \ Test.check()+}++concrete Test {+  @type check () -> ()+}++define Test {+  check () {+    \ Testing.checkEquals<?>(1 `one` 2 `two` 4,5)+  }++  @type one (Int,Int) -> (Int)+  one (x,y) {+    \ Testing.checkEquals<?>(x,1)+    \ Testing.checkEquals<?>(y,2)+    return 3+  }++  @type two (Int,Int) -> (Int)+  two (x,y) {+    \ Testing.checkEquals<?>(x,3)+    \ Testing.checkEquals<?>(y,4)+    return 5+  }+}
tests/infix-operations.0rt view
@@ -107,7 +107,7 @@  unittest precedence {   scoped {-    Bool x <- false && false || true+    Bool x <- 1 < 2 && 3 <= 4   } in if (!x) {     fail(x)   }@@ -133,7 +133,21 @@   } } +unittest rightAssociative {+  Int x <- 2+  Bool y <- true && (x <- 3) == 2 || x == 3+  \ Testing.checkEquals<?>(x,3)+  \ Testing.checkEquals<?>(y,true)+} +unittest shortCircuit {+  Int x <- 2+  Bool y <- true || (x <- 3) == 2 || x == 3+  \ Testing.checkEquals<?>(x,2)+  \ Testing.checkEquals<?>(y,true)+}++ testcase "Float operations" {   success }@@ -316,7 +330,7 @@  define Test {   run () {-    \ 1 < 2 < 3+    \ (1 < 2) < 3   } } 
tests/regressions.0rt view
@@ -176,3 +176,86 @@     return "return"   } }+++testcase "Issue #126 is fixed" {+  // https://github.com/ta0kira/zeolite/issues/126+  crash+  require "message,12345,false"+}++unittest test {+  \ Type.call()+}++concrete Type {+  @type call () -> (String,Int,Bool)+}++define Type {+  call () (x,y,z) {+    cleanup {+      // Primitive variables y and z need to be explicitly set separately from+      // the return tuple, since the former are stored separately.+      fail(x + "," + y.formatted() + "," + z.formatted())+    } in return "message", 12345, false+  }+}+++testcase "Issue #127 is fixed: if" {+  // https://github.com/ta0kira/zeolite/issues/127+  error+  require "cleanup"+  require "message.+initialized"+}++unittest test {+  \ Type.call()+}++concrete Type {+  @type call () -> (String)+}++define Type {+  call () (message) {+    cleanup {+      // Using message on the right side of && makes sure that message is still+      // counted as being required, despite possible short-circuiting.+      if (true && message != "message") {+        fail("failed")+      }+    } in {}+    return "return"+  }+}+++testcase "Issue #127 is fixed: while" {+  // https://github.com/ta0kira/zeolite/issues/127+  error+  require "cleanup"+  require "message.+initialized"+}++unittest test {+  \ Type.call()+}++concrete Type {+  @type call () -> (String)+}++define Type {+  call () (message) {+    cleanup {+      // Using message on the right side of && makes sure that message is still+      // counted as being required, despite possible short-circuiting.+      while (true && message != "message") {+        fail("failed")+      }+    } in {}+    return "return"+  }+}
tests/while.0rt view
@@ -35,22 +35,6 @@ }  -testcase "assign while condition" {-  error-  require "value.+initialized"-}--@value interface Value {}--concrete Test {}--define Test {-  @value process () -> (optional Value)-  process () (value) {-    while (present((value <- empty))) {}-  }-}- testcase "return while" {   error   require "return"@@ -443,5 +427,27 @@       }     }     return "return"+  }+}+++testcase "return set in predicate" {+  crash+  require "message"+}++unittest test {+  \ Value.process()+}++concrete Value {+  @type process () -> (String)+}++define Value {+  process () (message) {+    while ((message <- "message") != "") {+      fail(message)+    }   } }
zeolite-lang.cabal view
@@ -1,7 +1,7 @@ cabal-version:       2.2  name:                zeolite-lang-version:             0.11.0.0+version:             0.12.0.0 synopsis:            Zeolite is a statically-typed, general-purpose programming language.  description: