packages feed

zeolite-lang 0.23.0.0 → 0.24.0.0

raw patch · 354 files changed

+13154/−4968 lines, 354 filesdep ~basedep ~hashabledep ~megaparsec

Dependency ranges changed: base, hashable, megaparsec, mtl, time, transformers, unix

Files

ChangeLog.md view
@@ -1,5 +1,206 @@ # Revision history for zeolite-lang +## 0.24.0.0  -- 2023-12-09++### Language++* **[breaking]** In `testcase`, renames `crash` to `failure`.++* **[breaking]** Adds the `visibility` keyword to limit calling of+  `@value`/`@type` functions to specific type contexts. This is breaking because+  `visibility` is now reserved.++  ```text+  concrete Foo {+    visibility Bar, Baz  // Functions below here are only visible from Bar or Baz.++    @type call () -> ()+  }+  ```++* **[breaking]** Adds function delegation with `delegate` keyword.++  ```text+  concrete Foo {+    @type new1 (Int) -> (Foo)+    @type new2 (Int) -> (Foo)+  }++  define Foo {+    @value Int value++    new1 (value) {+      // Same as Foo{ value }.+      return delegate -> Foo+    }++    new2 (value) {+      // Same as new1(value).+      return delegate -> `new1`+    }+  }+  ```++  This is a breaking change because `delegate` is now reserved.++* **[breaking]** In `testcase`, you can now optionally include a type name that+  `defines Testcase` after `success`/`failure`. The test will automatically call+  `start()` and `finish()`, which is meant to allow custom checks upon test+  exit. This is breaking because `Testcase` is now reserved.++* **[breaking]** Adds instance identification with the `identify` keyword. This+  is breaking because `identify` is now reserved.++* **[fix]** Fixes parsing of comments that immediately follow operators, e.g.,+  the `/*b+*/` in `a+/*b+*/c`.++* **[fix]** Fixes checking that a `@type` function isn't called on a `@value`.++* **[fix]** Fixes cross-module visibility checks with `$TestsOnly$` in `.0rp`+  without `$ModuleOnly$`. This is primarily to detect if there's usage of a+  `$TestsOnly$` category from a `private_dep` in a `.0rp`.++* **[fix]** Updates parsing of `empty` to allow explicit type conversion, e.g.,+  `empty?String`.++* **[new]** Adds the option to provide _enforced_ labels for function args.++  ```text+  concrete Foo {+    // First arg has the label value:.+    @type bar (Int value:) -> ()+  }++  // ...++  // Callers _must_ use the label value:.+  \ Foo.bar(value: 1)+  ```++  Unlike with languages like C++, where the argument name in the function+  _declaration_ is irrelevant, this is primarily meant to clarify calls to+  functions with arguments whose purposes are ambiguous.++  Note that this _doesn't_ make arguments optional, nor does it allow reordering+  of arguments. Additionally, there's no requirement that the labels match the+  argument names, nor that the labels are even unique.++* **[new]** Adds the `<-|` operator to conditionally overwrite an `optional`+  variable if it's empty.++  ```text+  optional Int value <- empty+  value <-| 123  // Assigned, because value was empty.+  value <-| 456  // Not assigned, because value wasn't empty.+  ```++* **[new]** Adds the `&.` operator to conditionally call a function on an+  `optional` value.++  ```text+  optional Int value <- 123+  optional Formatted formatted <- value&.formatted()+  ```++* **[new]** Updates the return type of inline `<-` to use the type on the right+  side of the expression, rather than the variable's type.++  ```text+  optional Formatted value <- empty+  // Previously, the return type would've been optional Formatted.+  Int value2 <- (value <- 123)+  ```++* **[new]** Updates type inference to arbitrarily choose the lower bound when a+  param is bounded above and below with different types. Previously, the+  compiler would require specifying the param explicitly. This will make param+  inference succeed in more situations than it did previously.++* **[new]** Adds the `<->` operator to swap variable values. This can be used to+  swap the values of writable variables of the same type, i.e., _not_ marked as+  read-only via a pragma and not a function argument.++  ```text+  Int foo <- 123+  Int bar <- 456+  foo <-> bar+  ```++* **[new]** Allows hex, octal, and binary floating-point literals. (Exponents+  not allowed due to ambiguity during hex parsing.)++  ```text+  Float value1 <- \xFED.CBA+  Float value2 <- \o765.432+  Float value3 <- \b101.010+  ```++* **[new]** Adds the `$CallTrace$` macro to get a call trace for testing+  purposes.++### Libraries++* **[breaking]** Removes `Testing` from `lib/testing` entirely. Use the new+  testing approach instead. (More details in items further down.)++  ```text+  // Old way.++  testcase "my tests" {+    success+  }++  unittest test {+    \ Testing.checkEquals("something", "other")+    \ Testing.checkBetween(3, 2, 7)+  }+  ```++  ```text+  // New way.++  testcase "my tests" {+    success TestChecker  // <- allows lib/testing to manage test results+  }++  unittest test {+    \ "something" `Matches:with` CheckValue:equals("other")+    \ 3 `Matches:with` CheckValue:betweenEquals(2, 7)+  }+  ```++  Also see the `.0rp` files in `lib/testing`.++* **[breaking]** Removes `UtilTesting` from `lib/util` entirely. Use the new+  testing approach instead.++* **[new]** Adds the `TestChecker` `testcase` checker (see previous section) to+  `lib/testing` to help support custom matchers.++* **[new]** Adds support for custom value matchers in tests to `lib/testing`, as+  well as matchers for value comparisons, substring checks, floating-point+  epsilon, and container comparisons in `lib/testing`, `lib/util`, and+  `lib/container`. User-defined matchers can compose other matchers to+  customize matching of more complex value types.++* **[new]** Implements `SetReader<#k>` for `HashedMap<#k, #v>` and+  `SortedMap<#k, #v>` in `lib/container`.++* **[new]** Adds `tryValue` to `ErrorOr` in `lib/util`.++* **[fix]** Updates `BarrierWait` C++ implementation to compile for MacOS by+  adding runtime failures if the functionality is used. MacOS doesn't support+  thread barriers, so `lib/thread` previously didn't compile for MacOS.++### Compiler CLI++* **[new]** Allows single-`-` CLI options to be clustered, e.g., `-rfj8`, which+  is expanded to `-r`, `-f`, and `-j` `8`.++* **[behavior]** Clearer error messages for categories hidden by `$ModuleOnly$`,+  `$TestsOnly$`, and `private_deps`. Previously, the compiler would just say+  that the category wasn't found.+ ## 0.23.0.0  -- 2022-10-08  ### Language
base/.zeolite-module view
@@ -2,36 +2,41 @@ path: "base" extra_files: [   category_source {-    source: "base/src/Extension_Bool.cpp"+    source: "base/src/Builtin_Bool.cpp"     categories: [Bool]   }   category_source {-    source: "base/src/Extension_Char.cpp"+    source: "base/src/Builtin_Char.cpp"     categories: [Char]   }   category_source {-    source: "base/src/Extension_CharBuffer.cpp"+    source: "base/src/Builtin_CharBuffer.cpp"     categories: [CharBuffer]   }   category_source {-    source: "base/src/Extension_Float.cpp"+    source: "base/src/Builtin_Float.cpp"     categories: [Float]   }   category_source {-    source: "base/src/Extension_Int.cpp"+    source: "base/src/Builtin_Identifier.cpp"+    categories: [Identifier]+  }+  category_source {+    source: "base/src/Builtin_Int.cpp"     categories: [Int]   }   category_source {-    source: "base/src/Extension_String.cpp"+    source: "base/src/Builtin_String.cpp"     categories: [String]   }   category_source {-    source: "base/src/Extension_Pointer.cpp"+    source: "base/src/Builtin_Pointer.cpp"     categories: [Pointer]   }   "base/boxed.hpp"   "base/category-header.hpp"   "base/category-source.hpp"+  "base/cleanup.hpp"   "base/cycle-check.hpp"   "base/function.hpp"   "base/logging.hpp"@@ -42,8 +47,9 @@   "base/types.hpp"   "base/src/boxed.cpp"   "base/src/category-source.cpp"+  "base/src/cleanup.cpp"   "base/src/logging.cpp"   "base/src/returns.cpp"   "base/src/thread-crosser.cc" ]-mode: incremental {}+mode: incremental { }
base/boxed.hpp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021-2022 Kevin P. Barry+Copyright 2021-2023 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.@@ -30,7 +30,15 @@ class ValueFunction;  namespace zeolite_internal {+class WeakValue;+class BoxedValue;+}  // namespace zeolite_internal +void SwapValues(zeolite_internal::WeakValue&, zeolite_internal::WeakValue&);+void SwapValues(zeolite_internal::BoxedValue&, zeolite_internal::BoxedValue&);++namespace zeolite_internal {+ struct UnionValue {   enum class Type : char {     EMPTY,@@ -39,6 +47,7 @@     INT,     FLOAT,     POINTER,+    IDENTIFIER,     BOXED,   }; @@ -46,6 +55,8 @@     std::atomic_flag lock_;     std::atomic_int strong_;     std::atomic_int weak_;+    // NOTE: This can't be optimized out because it might differ from the+    // pointer to the underlying object, e.g., if TypeValue is a virtual base.     TypeValue* object_;   }; @@ -55,16 +66,16 @@    union {     unsigned char* as_bytes_;-    Pointer*    as_boxed_;-    PrimBool    as_bool_;-    PrimChar    as_char_;-    PrimInt     as_int_;-    PrimFloat   as_float_;-    PrimPointer as_pointer_;+    Pointer*       as_boxed_;+    PrimBool       as_bool_;+    PrimChar       as_char_;+    PrimInt        as_int_;+    PrimFloat      as_float_;+    PrimPointer    as_pointer_;+    PrimIdentifier as_identifier_;   } __attribute__((packed)) value_; } __attribute__((packed)); - class BoxedValue {  public:   constexpr BoxedValue()@@ -116,27 +127,28 @@     return *this;   } -  inline BoxedValue(PrimBool value)+  inline explicit BoxedValue(PrimBool value)     : union_{ .type_ = UnionValue::Type::BOOL, .value_ = { .as_bool_ = value } } {} -  inline BoxedValue(PrimChar value)+  inline explicit BoxedValue(PrimChar value)     : union_{ .type_ = UnionValue::Type::CHAR, .value_ = { .as_char_ = value } } {} -  inline BoxedValue(PrimInt value)+  inline explicit BoxedValue(PrimInt value)     : union_{ .type_ = UnionValue::Type::INT, .value_ = { .as_int_ = value } } {} -  inline BoxedValue(PrimFloat value)+  inline explicit BoxedValue(PrimFloat value)     : union_{ .type_ = UnionValue::Type::FLOAT, .value_ = { .as_float_ = value } } {} -  inline BoxedValue(PrimPointer value)+  inline explicit BoxedValue(PrimPointer value)     : union_{ .type_ = UnionValue::Type::POINTER, .value_ = { .as_pointer_ = value } } {} +  inline explicit BoxedValue(PrimIdentifier value)+    : union_{ .type_ = UnionValue::Type::IDENTIFIER, .value_ = { .as_identifier_ = value } } {}+   template<class T, class... As>   static inline BoxedValue New(const As&... args) {     using Pointer = UnionValue::Pointer;-    BoxedValue new_value;-    new_value.union_.type_ = UnionValue::Type::BOXED;-    new_value.union_.value_.as_bytes_ = (unsigned char*) malloc(sizeof(Pointer) + sizeof(T));+    BoxedValue new_value(reinterpret_cast<unsigned char*>(malloc(sizeof(Pointer) + sizeof(T))));     new (new_value.union_.value_.as_bytes_)       Pointer{ ATOMIC_FLAG_INIT, {1}, {1},                {new (new_value.union_.value_.as_bytes_ + sizeof(Pointer)) T(args...)} };@@ -197,7 +209,7 @@   inline T* AsPointer() const {     switch (union_.type_) {       case UnionValue::Type::POINTER:-        return reinterpret_cast<T*>(union_.value_.as_boxed_);+        return reinterpret_cast<T*>(union_.value_.as_pointer_);       default:         FAIL() << union_.CategoryName() << " is not a Pointer value";         __builtin_unreachable();@@ -205,6 +217,17 @@     }   } +  inline PrimIdentifier AsIdentifier() const {+    switch (union_.type_) {+      case UnionValue::Type::IDENTIFIER:+        return union_.value_.as_identifier_;+      default:+        FAIL() << union_.CategoryName() << " is not an Identifier value";+        __builtin_unreachable();+        break;+    }+  }+   inline static bool Present(const BoxedValue& target) {     return target.union_.type_ != UnionValue::Type::EMPTY;   }@@ -224,6 +247,8 @@     return BoxedValue(target);   } +  static PrimIdentifier Identify(const BoxedValue& target);+   void Validate(const std::string& name) const;    const PrimString& AsString() const;@@ -232,7 +257,11 @@  private:   friend class ::TypeValue;   friend class WeakValue;+  friend void ::SwapValues(BoxedValue&, BoxedValue&); +  inline explicit BoxedValue(unsigned char* value)+    : union_{ .type_ = UnionValue::Type::BOXED, .value_ = { .as_bytes_ = value } } {}+   // Intentionally break old calls that used new.   inline explicit constexpr BoxedValue(void*) : BoxedValue() {} @@ -242,10 +271,7 @@    template<class T>   static inline BoxedValue FromPointer(const T* pointer) {-    BoxedValue value;-    value.union_.type_ = UnionValue::Type::BOXED;-    value.union_.value_.as_bytes_ =-      reinterpret_cast<unsigned char*>(const_cast<T*>(pointer))-sizeof(UnionValue::Pointer);+    BoxedValue value(reinterpret_cast<unsigned char*>(const_cast<T*>(pointer))-sizeof(UnionValue::Pointer));     if (value.union_.value_.as_boxed_->object_ != pointer ||         ++value.union_.value_.as_boxed_->strong_ == 1) {       FAIL() << "Bad VAR_SELF pointer " << pointer << " in " << pointer->CategoryName();@@ -279,6 +305,7 @@   private:   friend class BoxedValue;+  friend void ::SwapValues(WeakValue&, WeakValue&);    void Cleanup(); @@ -286,6 +313,19 @@ } __attribute__((packed));  }  // namespace zeolite_internal+++inline void SwapValues(BoxedValue& left, BoxedValue& right) {+  zeolite_internal::UnionValue temp = right.union_;+  right.union_ = left.union_;+  left.union_ = temp;+}++inline void SwapValues(WeakValue& left, WeakValue& right) {+  zeolite_internal::UnionValue temp = right.union_;+  right.union_ = left.union_;+  left.union_ = temp;+}  using zeolite_internal::BoxedValue; using zeolite_internal::WeakValue;
base/builtin.0rp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -23,6 +23,7 @@ // Notes: // - You do not need () to make a function call on a literal; something like //   true.asInt() is totally fine.+// - Values are unboxed when storing in variables. concrete Bool {   immutable @@ -51,6 +52,7 @@ //   'a'.asInt() is totally fine. // - When converting to Int with asInt(), the value will always be unsigned, //   i.e., beween 0-255. ASCII characters will be in the 0-127 range.+// - Values are unboxed when storing in variables. concrete Char {   immutable @@ -73,9 +75,13 @@ // Literals: // - . required, with at least one digit on either side, e.g., 0.1 // - Scientific notation: 0.1E-10, etc.+// - Hex:    \xABC.DEF, etc.+// - Octal:  \o777.266, etc.+// - Binary: \b011.011, etc. // // Notes: // - You must use () to make a function call on a literal, e.g, (1.1).asInt().+// - Values are unboxed when storing in variables. concrete Float {   immutable @@ -103,11 +109,10 @@ // - Overflow will cause a compilation error. // - Hex, oct, and binary escapes can go up to 2^64-1 to allow use of all 64 //   bits, but they will still be used as signed values.-//-// Notes: // - You must use () to make a function call on a literal, e.g, (100).asFloat(). // - When converting to Char with asChar(), the value will always be treated as //   unsigned, i.e., beween 0-255 mod 256.+// - Values are unboxed when storing in variables. concrete Int {   immutable @@ -160,7 +165,7 @@   // Example:   //   //   String.builder().append("foo").append("bar").build()-  @type builder () -> ([Append<Formatted>&Build<String>])+  @type builder () -> ([Append<Formatted> & Build<String>]) }  // Built-in fixed-size buffer of byte data.@@ -194,10 +199,33 @@ //   values with incompatible types. // - This is category is only meant for passing C++ data between extensions when //   it would otherwise require marshaling, which is why it has no functions.+// - Values are unboxed when storing in variables. concrete Pointer<#x> {   immutable } +// An identifier for a value instance.+//+// Literals: None.+//+// Notes:+// - Get an Identifier<#x> from optional #x value with instance(value).+// - Also supports comparisons, e.g., <, ==.+// - Values are unboxed when storing in variables.+// - Identifiers will be unique for different concrete values if:+//   - Both underlying concrete types are unboxed, which is the case with all+//     custom concrete types.+//   - Both values existed at the same time at some point.+concrete Identifier<|#x> {+  immutable++  refines Formatted+  refines Hashed++  defines Equals<Identifier<any>>+  defines LessThan<Identifier<any>>+}+ // Convertible to Bool. @value interface AsBool {   // Convert the value to Bool.@@ -330,7 +358,7 @@   refines Container    // Write the value at the given index and return self.-  writeAt (Int,#x) -> (#self)+  writeAt (Int, #x) -> (#self) }  // Sequence that can be subsequenced.@@ -338,7 +366,7 @@   refines Container    // Return a copy of a subsequence.-  subSequence (Int,Int) -> (#self)+  subSequence (Int, Int) -> (#self) }  // The type has a default value.@@ -365,7 +393,7 @@ // - #x: The value type to be compared. @type interface Equals<#x|> {   // Returns true iff the two values are equal. Must be symmetric.-  equals (#x,#x) -> (Bool)+  equals (#x, #x) -> (Bool) }  // The type can compare values for less-than.@@ -374,5 +402,5 @@ // - #x: The value type to be compared. @type interface LessThan<#x|> {   // Returns true iff the first value is less than the second.-  lessThan (#x,#x) -> (Bool)+  lessThan (#x, #x) -> (Bool) }
base/category-source.hpp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -26,6 +26,7 @@ #include <vector>  #include "boxed.hpp"+#include "cleanup.hpp" #include "cycle-check.hpp" #include "function.hpp" #include "returns.hpp"@@ -39,7 +40,9 @@   }  #define BUILTIN_EXIT(e) { \-    std::exit(e); \+    int code = e; \+    GlobalCleanup::Finish(code); \+    std::exit(code); \     __builtin_unreachable(); \   } @@ -73,6 +76,10 @@   return BoxedValue(reinterpret_cast<PrimPointer>(static_cast<T1*>(value))); } +inline BoxedValue Box_Identifier(PrimIdentifier value) {+  return BoxedValue(value);+}+ BoxedValue Box_String(const PrimString& value);  S<const TypeInstance> Merge_Intersect(const L<S<const TypeInstance>>& params);@@ -178,6 +185,13 @@   } }; +#define TYPE_VALUE_CALL_UNLESS_EMPTY(expr, func, args, count) ({ \+    const BoxedValue result = expr; \+    BoxedValue::Present(result) \+        ? TypeValue::Call(result, func, args) \+        : ReturnTuple(count); \+    })+ class TypeValue {  public:   inline static ReturnTuple Call(const BoxedValue& target, const ValueFunction& label,@@ -254,5 +268,9 @@   std::atomic_flag lock_ = ATOMIC_FLAG_INIT;   std::map<typename ParamsKey<P>::Type, W<T>> cache_; };++#ifdef ZEOLITE_TESTS_ONLY__YOUR_MODULE_IS_BROKEN_IF_YOU_USE_THIS_IN_HAND_WRITTEN_CODE+BoxedValue GetCallTrace(const ValueFunction& get_func, const ValueFunction& next_func);+#endif  #endif  // CATEGORY_SOURCE_HPP_
+ base/cleanup.hpp view
@@ -0,0 +1,56 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++#ifndef CLEANUP_HPP_+#define CLEANUP_HPP_++#include "thread-capture.h"+#include "category-header.hpp"+++class GlobalCleanup : public capture_thread::ThreadCapture<GlobalCleanup> {+ public:+  // Executes cleanup routines in reverse order.+  static void Finish(int code);++ protected:+  // NOTE: Each destructor should call Cleanup().+  virtual ~GlobalCleanup() = default;+  virtual GlobalCleanup* GetNext() const = 0;+  virtual void Cleanup(int code) = 0;+};++// Executes type functions upon construction and destruction.+class WrapTypeCall : public GlobalCleanup {+ public:+  // Both start and finish take no args. finish is only called once, whether+  // it's via Finish() or the destructor.+  WrapTypeCall(S<const TypeInstance> type, const TypeFunction* start, const TypeFunction* finish);+  ~WrapTypeCall();++ protected:+  GlobalCleanup* GetNext() const override;+  void Cleanup(int code) override;++ private:+  const S<const TypeInstance> type_;+  const TypeFunction* finish_;+  const AutoThreadCrosser cross_and_capture_to_;+};++#endif  // CLEANUP_HPP_
+ base/src/Builtin_Bool.cpp view
@@ -0,0 +1,100 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2022 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]++#include "category-source.hpp"+#include "Streamlined_Bool.hpp"+#include "Category_AsBool.hpp"+#include "Category_AsFloat.hpp"+#include "Category_AsInt.hpp"+#include "Category_Bool.hpp"+#include "Category_Default.hpp"+#include "Category_Duplicate.hpp"+#include "Category_Equals.hpp"+#include "Category_Float.hpp"+#include "Category_Formatted.hpp"+#include "Category_Hashed.hpp"+#include "Category_Int.hpp"+#include "Category_String.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++struct ExtCategory_Bool : public Category_Bool {+};++struct ExtType_Bool : public Type_Bool {+  inline ExtType_Bool(Category_Bool& p, Params<0>::Type params) : Type_Bool(p, params) {}++  ReturnTuple Call_default(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Bool.default")+    return ReturnTuple(Box_Bool(false));+  }++  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Bool.equals")+    const PrimBool Var_arg1 = (params_args.GetArg(0)).AsBool();+    const PrimBool Var_arg2 = (params_args.GetArg(1)).AsBool();+    return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));+  }++  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Bool.lessThan")+    const PrimBool Var_arg1 = (params_args.GetArg(0)).AsBool();+    const PrimBool Var_arg2 = (params_args.GetArg(1)).AsBool();+    return ReturnTuple(Box_Bool(!Var_arg1 && Var_arg2));+  }+};++ReturnTuple DispatchBool(PrimBool value, const ValueFunction& label,+                         const ParamsArgs& params_args) {+  switch (label.collection) {+    case CategoryId_AsBool:+      return ReturnTuple(Box_Bool(value));+    case CategoryId_AsFloat:+      return ReturnTuple(Box_Float(value ? 1.0 : 0.0));+    case CategoryId_AsInt:+      return ReturnTuple(Box_Int(value? 1 : 0));+    case CategoryId_Duplicate:+      return ReturnTuple(Box_Bool(value));+    case CategoryId_Formatted:+      return ReturnTuple(Box_String(value? "true" : "false"));+    case CategoryId_Hashed:+      return ReturnTuple(Box_Int(value ? 1000000009ULL : 1000000007ULL));+    default:+      FAIL() << "Bool does not implement " << label;+      __builtin_unreachable();+  }+}++Category_Bool& CreateCategory_Bool() {+  static auto& category = *new ExtCategory_Bool();+  return category;+}++S<const Type_Bool> CreateType_Bool(const Params<0>::Type& params) {+  static const auto cached = S_get(new ExtType_Bool(CreateCategory_Bool(), Params<0>::Type()));+  return cached;+}++void RemoveType_Bool(const Params<0>::Type& params) {}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+ base/src/Builtin_Char.cpp view
@@ -0,0 +1,115 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2022 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]++#include "category-source.hpp"+#include "Streamlined_Char.hpp"+#include "Category_AsBool.hpp"+#include "Category_AsChar.hpp"+#include "Category_AsFloat.hpp"+#include "Category_AsInt.hpp"+#include "Category_Bool.hpp"+#include "Category_Char.hpp"+#include "Category_Default.hpp"+#include "Category_Duplicate.hpp"+#include "Category_Equals.hpp"+#include "Category_Float.hpp"+#include "Category_Formatted.hpp"+#include "Category_Hashed.hpp"+#include "Category_Int.hpp"+#include "Category_LessThan.hpp"+#include "Category_String.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++struct ExtCategory_Char : public Category_Char {+};++struct ExtType_Char : public Type_Char {+  inline ExtType_Char(Category_Char& p, Params<0>::Type params) : Type_Char(p, params) {}++  ReturnTuple Call_maxBound(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Char.maxBound")+    return ReturnTuple(Box_Char('\xff'));+  }++  ReturnTuple Call_minBound(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Char.minBound")+    return ReturnTuple(Box_Char('\0'));+  }++  ReturnTuple Call_default(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Char.default")+    return ReturnTuple(Box_Char('\0'));+  }++  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Char.equals")+    const PrimChar Var_arg1 = (params_args.GetArg(0)).AsChar();+    const PrimChar Var_arg2 = (params_args.GetArg(1)).AsChar();+    return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));+  }++  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Char.lessThan")+    const PrimChar Var_arg1 = (params_args.GetArg(0)).AsChar();+    const PrimChar Var_arg2 = (params_args.GetArg(1)).AsChar();+    return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));+  }+};++ReturnTuple DispatchChar(PrimChar value, const ValueFunction& label,+                         const ParamsArgs& params_args) {+  switch (label.collection) {+    case CategoryId_AsBool:+      return ReturnTuple(Box_Bool(value != '\0'));+    case CategoryId_AsChar:+      return ReturnTuple(Box_Char(value));+    case CategoryId_AsFloat:+      return ReturnTuple(Box_Float(((int) value + 256) % 256));+    case CategoryId_AsInt:+      return ReturnTuple(Box_Int(((int) value + 256) % 256));+    case CategoryId_Duplicate:+      return ReturnTuple(Box_Char(value));+    case CategoryId_Formatted:+      return ReturnTuple(Box_String(PrimString(1, value)));+    case CategoryId_Hashed:+      return ReturnTuple(Box_Int(1000000009ULL * ((unsigned long long) value + 1000000007ULL)));+    default:+      FAIL() << "Char does not implement " << label;+      __builtin_unreachable();+  }+}++Category_Char& CreateCategory_Char() {+  static auto& category = *new ExtCategory_Char();+  return category;+}++S<const Type_Char> CreateType_Char(const Params<0>::Type& params) {+  static const auto cached = S_get(new ExtType_Char(CreateCategory_Char(), Params<0>::Type()));+  return cached;+}++void RemoveType_Char(const Params<0>::Type& params) {}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+ base/src/Builtin_CharBuffer.cpp view
@@ -0,0 +1,115 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2021 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]++#include "category-source.hpp"+#include "Streamlined_CharBuffer.hpp"+#include "Category_Char.hpp"+#include "Category_CharBuffer.hpp"+#include "Category_Container.hpp"+#include "Category_Int.hpp"+#include "Category_ReadAt.hpp"+#include "Category_WriteAt.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++BoxedValue CreateValue_CharBuffer(S<const Type_CharBuffer> parent, PrimCharBuffer buffer);++struct ExtCategory_CharBuffer : public Category_CharBuffer {+};++struct ExtType_CharBuffer : public Type_CharBuffer {+  inline ExtType_CharBuffer(Category_CharBuffer& p, Params<0>::Type params) : Type_CharBuffer(p, params) {}++  ReturnTuple Call_new(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("CharBuffer.new")+    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();+    if (Var_arg1 < 0) {+      FAIL() << "Buffer size " << Var_arg1 << " is invalid";+    }+    return ReturnTuple(CreateValue_CharBuffer(CreateType_CharBuffer(Params<0>::Type()), PrimCharBuffer(Var_arg1,'\0')));+  }+};++struct ExtValue_CharBuffer : public Value_CharBuffer {+  inline ExtValue_CharBuffer(S<const Type_CharBuffer> p, PrimCharBuffer value)+    : Value_CharBuffer(std::move(p)), value_(std::move(value)) {}++  ReturnTuple Call_readAt(const ParamsArgs& params_args) final {+    TRACE_FUNCTION("CharBuffer.readAt")+    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();+    if (Var_arg1 < 0 || Var_arg1 >= AsCharBuffer().size()) {+      FAIL() << "Read position " << Var_arg1 << " is out of bounds";+    }+    return ReturnTuple(Box_Char(AsCharBuffer()[Var_arg1]));+  }++  ReturnTuple Call_resize(const ParamsArgs& params_args) final {+    TRACE_FUNCTION("CharBuffer.resize")+    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();+    if (Var_arg1 < 0) {+      FAIL() << "Buffer size " << Var_arg1 << " is invalid";+    } else {+      value_.resize(Var_arg1);+    }+    return ReturnTuple(VAR_SELF);+  }++  ReturnTuple Call_size(const ParamsArgs& params_args) final {+    TRACE_FUNCTION("CharBuffer.size")+    return ReturnTuple(Box_Int(value_.size()));+  }++  ReturnTuple Call_writeAt(const ParamsArgs& params_args) final {+    TRACE_FUNCTION("CharBuffer.writeAt")+    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();+    const PrimChar Var_arg2 = (params_args.GetArg(1)).AsChar();+    if (Var_arg1 < 0 || Var_arg1 >= value_.size()) {+      FAIL() << "Write position " << Var_arg1 << " is out of bounds";+    } else {+      value_[Var_arg1] = Var_arg2;+    }+    return ReturnTuple(VAR_SELF);+  }++  PrimCharBuffer& AsCharBuffer() final { return value_; }++  PrimCharBuffer value_;+};++Category_CharBuffer& CreateCategory_CharBuffer() {+  static auto& category = *new ExtCategory_CharBuffer();+  return category;+}++S<const Type_CharBuffer> CreateType_CharBuffer(const Params<0>::Type& params) {+  static const auto cached = S_get(new ExtType_CharBuffer(CreateCategory_CharBuffer(), Params<0>::Type()));+  return cached;+}++void RemoveType_CharBuffer(const Params<0>::Type& params) {}++BoxedValue CreateValue_CharBuffer(S<const Type_CharBuffer> parent, PrimCharBuffer value) {+  return BoxedValue::New<ExtValue_CharBuffer>(std::move(parent), std::move(value));+}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+ base/src/Builtin_Float.cpp view
@@ -0,0 +1,107 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2022 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]++#include <sstream>++#include "category-source.hpp"+#include "Streamlined_Float.hpp"+#include "Category_AsBool.hpp"+#include "Category_AsFloat.hpp"+#include "Category_AsInt.hpp"+#include "Category_Bool.hpp"+#include "Category_Default.hpp"+#include "Category_Duplicate.hpp"+#include "Category_Equals.hpp"+#include "Category_Float.hpp"+#include "Category_Formatted.hpp"+#include "Category_Hashed.hpp"+#include "Category_Int.hpp"+#include "Category_LessThan.hpp"+#include "Category_String.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++struct ExtCategory_Float : public Category_Float {+};++struct ExtType_Float : public Type_Float {+  inline ExtType_Float(Category_Float& p, Params<0>::Type params) : Type_Float(p, params) {}++  ReturnTuple Call_default(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Float.default")+    return ReturnTuple(Box_Float(0.0));+  }++  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Float.equals")+    const PrimFloat Var_arg1 = (params_args.GetArg(0)).AsFloat();+    const PrimFloat Var_arg2 = (params_args.GetArg(1)).AsFloat();+    return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));+  }++  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Float.lessThan")+    const PrimFloat Var_arg1 = (params_args.GetArg(0)).AsFloat();+    const PrimFloat Var_arg2 = (params_args.GetArg(1)).AsFloat();+    return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));+  }+};++ReturnTuple DispatchFloat(PrimFloat value, const ValueFunction& label,+                          const ParamsArgs& params_args) {+  switch (label.collection) {+    case CategoryId_AsBool:+      return ReturnTuple(Box_Bool(value != 0.0));+    case CategoryId_AsFloat:+      return ReturnTuple(Box_Float(value));+    case CategoryId_AsInt:+      return ReturnTuple(Box_Int(value));+    case CategoryId_Duplicate:+      return ReturnTuple(Box_Float(value));+    case CategoryId_Formatted: {+      // NOTE: std::to_string does weird things with significant digits.+      std::ostringstream output;+      output << value;+      return ReturnTuple(Box_String(output.str()));+    }+    case CategoryId_Hashed:+      return ReturnTuple(Box_Int(1000000009ULL * reinterpret_cast<uint64_t&>(value)));+    default:+      FAIL() << "Float does not implement " << label;+      __builtin_unreachable();+  }+}++Category_Float& CreateCategory_Float() {+  static auto& category = *new ExtCategory_Float();+  return category;+}++S<const Type_Float> CreateType_Float(const Params<0>::Type& params) {+  static const auto cached = S_get(new ExtType_Float(CreateCategory_Float(), Params<0>::Type()));+  return cached;+}++void RemoveType_Float(const Params<0>::Type& params) {}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+ base/src/Builtin_Identifier.cpp view
@@ -0,0 +1,98 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++#include <iomanip>+#include <sstream>++#include "category-source.hpp"+#include "Streamlined_Identifier.hpp"+#include "Category_Equals.hpp"+#include "Category_Formatted.hpp"+#include "Category_Hashed.hpp"+#include "Category_LessThan.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++struct ExtCategory_Identifier : public Category_Identifier {+};++struct ExtType_Identifier : public Type_Identifier {+  inline ExtType_Identifier(Category_Identifier& p, Params<1>::Type params) : Type_Identifier(p, params) {}++  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Identifier.equals")+    const PrimIdentifier Var_arg1 = (params_args.GetArg(0)).AsIdentifier();+    const PrimIdentifier Var_arg2 = (params_args.GetArg(1)).AsIdentifier();+    return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));+  }++  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Identifier.lessThan")+    const PrimIdentifier Var_arg1 = (params_args.GetArg(0)).AsIdentifier();+    const PrimIdentifier Var_arg2 = (params_args.GetArg(1)).AsIdentifier();+    return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));+  }+};++PrimIdentifier RandomizeIdentifier(PrimIdentifier identifier) {+  // This is random enough. It only needs to be odd.+  const static auto MULTIPLIER =+    ((unsigned long long) &CreateCategory_Identifier())+    + 1 - (1 & (unsigned long long) &CreateCategory_Identifier());+  return reinterpret_cast<PrimIdentifier>(MULTIPLIER * MULTIPLIER * ((unsigned long long) identifier));+}++ReturnTuple DispatchIdentifier(PrimIdentifier value, const ValueFunction& label,+                               const ParamsArgs& params_args) {+  switch (label.collection) {+    case CategoryId_Formatted: {+      std::ostringstream output;+      output << std::hex << std::setfill('0') << std::setw(16) << (unsigned long long) value;+      return ReturnTuple(Box_String(output.str()));+    }+    case CategoryId_Hashed:+      return ReturnTuple(Box_Int(1000000009ULL * ((unsigned long long) value + 1000000007ULL)));+    default:+      FAIL() << "Identifier does not implement " << label;+      __builtin_unreachable();+  }+}++Category_Identifier& CreateCategory_Identifier() {+  static auto& category = *new ExtCategory_Identifier();+  return category;+}++static auto& Identifier_instance_cache = *new InstanceCache<1, Type_Identifier>([](const Params<1>::Type& params) {+    return S_get(new ExtType_Identifier(CreateCategory_Identifier(), params));+  });++S<const Type_Identifier> CreateType_Identifier(const Params<1>::Type& params) {+  return Identifier_instance_cache.GetOrCreate(params);+}++void RemoveType_Identifier(const Params<1>::Type& params) {+  Identifier_instance_cache.Remove(params);+}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+ base/src/Builtin_Int.cpp view
@@ -0,0 +1,118 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2022 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]++#include <climits>+#include <string>++#include "category-source.hpp"+#include "Streamlined_Int.hpp"+#include "Category_AsBool.hpp"+#include "Category_AsChar.hpp"+#include "Category_AsFloat.hpp"+#include "Category_AsInt.hpp"+#include "Category_Bool.hpp"+#include "Category_Char.hpp"+#include "Category_Default.hpp"+#include "Category_Duplicate.hpp"+#include "Category_Equals.hpp"+#include "Category_Float.hpp"+#include "Category_Formatted.hpp"+#include "Category_Hashed.hpp"+#include "Category_Int.hpp"+#include "Category_LessThan.hpp"+#include "Category_String.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++struct ExtCategory_Int : public Category_Int {+};++struct ExtType_Int : public Type_Int {+  inline ExtType_Int(Category_Int& p, Params<0>::Type params) : Type_Int(p, params) {}++  ReturnTuple Call_maxBound(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Int.maxBound")+    return ReturnTuple(Box_Int(9223372036854775807LL));+  }++  ReturnTuple Call_minBound(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Int.minBound")+    return ReturnTuple(Box_Int(-9223372036854775807LL - 1LL));+  }++  ReturnTuple Call_default(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Int.default")+    return ReturnTuple(Box_Int(0));+  }++  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Int.equals")+    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();+    const PrimInt Var_arg2 = (params_args.GetArg(1)).AsInt();+    return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));+  }++  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("Int.lessThan")+    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();+    const PrimInt Var_arg2 = (params_args.GetArg(1)).AsInt();+    return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));+  }+};++ReturnTuple DispatchInt(PrimInt value, const ValueFunction& label,+                        const ParamsArgs& params_args) {+  switch (label.collection) {+    case CategoryId_AsBool:+      return ReturnTuple(Box_Bool(value != 0));+    case CategoryId_AsChar:+      return ReturnTuple(Box_Char(PrimChar(((value % 256) + 256) % 256)));+    case CategoryId_AsFloat:+      return ReturnTuple(Box_Float(value));+    case CategoryId_AsInt:+      return ReturnTuple(Box_Int(value));+    case CategoryId_Duplicate:+      return ReturnTuple(Box_Int(value));+    case CategoryId_Formatted:+      return ReturnTuple(Box_String(std::to_string(value)));+    case CategoryId_Hashed:+      return ReturnTuple(Box_Int(1000000007ULL * value));+    default:+      FAIL() << "Int does not implement " << label;+      __builtin_unreachable();+  }+}++Category_Int& CreateCategory_Int() {+  static auto& category = *new ExtCategory_Int();+  return category;+}++S<const Type_Int> CreateType_Int(const Params<0>::Type& params) {+  static const auto cached = S_get(new ExtType_Int(CreateCategory_Int(), Params<0>::Type()));+  return cached;+}++void RemoveType_Int(const Params<0>::Type& params) {}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+ base/src/Builtin_Pointer.cpp view
@@ -0,0 +1,62 @@+/* -----------------------------------------------------------------------------+Copyright 2022 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]++#include "category-source.hpp"+#include "Streamlined_Pointer.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++struct ExtCategory_Pointer : public Category_Pointer {+};++struct ExtType_Pointer : public Type_Pointer {+  inline ExtType_Pointer(Category_Pointer& p, Params<1>::Type params) : Type_Pointer(p, params) {}+};++ReturnTuple DispatchPointer(PrimPointer value, const ValueFunction& label,+                            const ParamsArgs& params_args) {+  switch (label.collection) {+    default:+      FAIL() << "Pointer does not implement " << label;+      __builtin_unreachable();+  }+}++Category_Pointer& CreateCategory_Pointer() {+  static auto& category = *new ExtCategory_Pointer();+  return category;+}++static auto& Pointer_instance_cache = *new InstanceCache<1, Type_Pointer>([](const Params<1>::Type& params) {+    return S_get(new ExtType_Pointer(CreateCategory_Pointer(), params));+  });++S<const Type_Pointer> CreateType_Pointer(const Params<1>::Type& params) {+  return Pointer_instance_cache.GetOrCreate(params);+}++void RemoveType_Pointer(const Params<1>::Type& params) {+  Pointer_instance_cache.Remove(params);+}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+ base/src/Builtin_String.cpp view
@@ -0,0 +1,228 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2021 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]++#include "category-source.hpp"+#include "Streamlined_String.hpp"+#include "Category_Append.hpp"+#include "Category_AsBool.hpp"+#include "Category_Bool.hpp"+#include "Category_Build.hpp"+#include "Category_Char.hpp"+#include "Category_CharBuffer.hpp"+#include "Category_Container.hpp"+#include "Category_Default.hpp"+#include "Category_DefaultOrder.hpp"+#include "Category_Duplicate.hpp"+#include "Category_Equals.hpp"+#include "Category_Formatted.hpp"+#include "Category_Hashed.hpp"+#include "Category_Int.hpp"+#include "Category_LessThan.hpp"+#include "Category_Order.hpp"+#include "Category_ReadAt.hpp"+#include "Category_String.hpp"+#include "Category_SubSequence.hpp"++#ifdef ZEOLITE_PUBLIC_NAMESPACE+namespace ZEOLITE_PUBLIC_NAMESPACE {+#endif  // ZEOLITE_PUBLIC_NAMESPACE++struct ExtCategory_String : public Category_String {+};++class Value_StringBuilder : public TypeValue {+ public:+  std::string CategoryName() const final { return "StringBuilder"; }++  ReturnTuple Dispatch(const ValueFunction& label,+                       const ParamsArgs& params_args) final {+    if (&label == &Function_Append_append) {+      TRACE_FUNCTION("StringBuilder.append")+      std::lock_guard<std::mutex> lock(mutex);+      output_ << TypeValue::Call(params_args.GetArg(0), Function_Formatted_formatted, PassParamsArgs()).At(0).AsString();+      return ReturnTuple(VAR_SELF);+    }+    if (&label == &Function_Build_build) {+      TRACE_FUNCTION("StringBuilder.build")+      std::lock_guard<std::mutex> lock(mutex);+      return ReturnTuple(Box_String(output_.str()));+    }+    return TypeValue::Dispatch(label, params_args);+  }++ private:+  std::mutex mutex;+  std::ostringstream output_;+};++struct ExtType_String : public Type_String {+  inline ExtType_String(Category_String& p, Params<0>::Type params) : Type_String(p, params) {}++  ReturnTuple Call_builder(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.builder")+    return ReturnTuple(BoxedValue::New<Value_StringBuilder>());+  }++  ReturnTuple Call_default(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.default")+    return ReturnTuple(Box_String(""));+  }++  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.equals")+    const BoxedValue& Var_arg1 = (params_args.GetArg(0));+    const BoxedValue& Var_arg2 = (params_args.GetArg(1));+    return ReturnTuple(Box_Bool(Var_arg1.AsString()==Var_arg2.AsString()));+  }++  ReturnTuple Call_fromCharBuffer(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.fromCharBuffer")+    const BoxedValue& Var_arg1 = (params_args.GetArg(0));+    return ReturnTuple(Box_String(PrimString(Var_arg1.AsCharBuffer())));+  }++  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.lessThan")+    const BoxedValue& Var_arg1 = (params_args.GetArg(0));+    const BoxedValue& Var_arg2 = (params_args.GetArg(1));+    return ReturnTuple(Box_Bool(Var_arg1.AsString()<Var_arg2.AsString()));+  }+};++class StringOrder : public TypeValue {+ public:+  StringOrder(BoxedValue container, const std::string& s)+    : container_(container), value_(s) {}++  std::string CategoryName() const final { return "StringOrder"; }++  ReturnTuple Dispatch(const ValueFunction& label, const ParamsArgs& params_args) final {+    if (&label == &Function_Order_next) {+      TRACE_FUNCTION("StringOrder.next")+      if (index_+1 >= value_.size()) {+        return ReturnTuple(Var_empty);+      } else {+        ++index_;+        return ReturnTuple(VAR_SELF);+      }+    }+    if (&label == &Function_Order_get) {+      TRACE_FUNCTION("StringOrder.get")+      if (index_ >= value_.size()) {+        FAIL() << "Iterated past end of String";+      }+      return ReturnTuple(Box_Char(value_[index_]));+    }+    return TypeValue::Dispatch(label, params_args);+  }++ private:+  const BoxedValue container_;+  const std::string& value_;+  int index_ = 0;+};++struct ExtValue_String : public Value_String {+  inline ExtValue_String(S<const Type_String> p, const PrimString& value)+    : Value_String(std::move(p)), value_(value) {}++  ReturnTuple Call_asBool(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.asBool")+    return ReturnTuple(Box_Bool(value_.size() != 0));+  }++  ReturnTuple Call_defaultOrder(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.defaultOrder")+    if (value_.empty()) {+      return ReturnTuple(Var_empty);+    } else {+      return ReturnTuple(BoxedValue::New<StringOrder>(VAR_SELF, value_));+    }+  }++  ReturnTuple Call_duplicate(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.duplicate")+    return ReturnTuple(VAR_SELF);+  }++  ReturnTuple Call_formatted(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.formatted")+    return ReturnTuple(VAR_SELF);+  }++  ReturnTuple Call_hashed(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.hashed")+    PrimInt hash = 1000000009ULL;+    for (char c : value_) {+      hash = hash * 1000000009ULL + (unsigned long long) c * 1000000007ULL;+    }+    return ReturnTuple(Box_Int(hash));+  }++  ReturnTuple Call_readAt(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.readAt")+    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();+    if (Var_arg1 < 0 || Var_arg1 >= value_.size()) {+      FAIL() << "Read position " << Var_arg1 << " is out of bounds";+    }+    return ReturnTuple(Box_Char(value_[Var_arg1]));+  }++  ReturnTuple Call_size(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.size")+    return ReturnTuple(Box_Int(value_.size()));+  }++  ReturnTuple Call_subSequence(const ParamsArgs& params_args) const final {+    TRACE_FUNCTION("String.subSequence")+    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();+    const PrimInt Var_arg2 = (params_args.GetArg(1)).AsInt();+    if (Var_arg1 < 0 || Var_arg1 > value_.size()) {+      FAIL() << "Subsequence position " << Var_arg1 << " is out of bounds";+    }+    if (Var_arg2 < 0 || Var_arg1 + Var_arg2 > value_.size()) {+      FAIL() << "Subsequence size " << Var_arg2 << " is invalid";+    }+    return ReturnTuple(Box_String(value_.substr(Var_arg1,Var_arg2)));+  }++  const PrimString& AsString() const final { return value_; }++  const PrimString value_;+};++Category_String& CreateCategory_String() {+  static auto& category = *new ExtCategory_String();+  return category;+}++S<const Type_String> CreateType_String(const Params<0>::Type& params) {+  static const auto cached = S_get(new ExtType_String(CreateCategory_String(), Params<0>::Type()));+  return cached;+}++void RemoveType_String(const Params<0>::Type& params) {}++#ifdef ZEOLITE_PUBLIC_NAMESPACE+}  // namespace ZEOLITE_PUBLIC_NAMESPACE+using namespace ZEOLITE_PUBLIC_NAMESPACE;+#endif  // ZEOLITE_PUBLIC_NAMESPACE++BoxedValue Box_String(const PrimString& value) {+  return BoxedValue::New<ExtValue_String>(CreateType_String(Params<0>::Type()), value);+}
− base/src/Extension_Bool.cpp
@@ -1,100 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2019-2022 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]--#include "category-source.hpp"-#include "Streamlined_Bool.hpp"-#include "Category_AsBool.hpp"-#include "Category_AsFloat.hpp"-#include "Category_AsInt.hpp"-#include "Category_Bool.hpp"-#include "Category_Default.hpp"-#include "Category_Duplicate.hpp"-#include "Category_Equals.hpp"-#include "Category_Float.hpp"-#include "Category_Formatted.hpp"-#include "Category_Hashed.hpp"-#include "Category_Int.hpp"-#include "Category_String.hpp"--#ifdef ZEOLITE_PUBLIC_NAMESPACE-namespace ZEOLITE_PUBLIC_NAMESPACE {-#endif  // ZEOLITE_PUBLIC_NAMESPACE--struct ExtCategory_Bool : public Category_Bool {-};--struct ExtType_Bool : public Type_Bool {-  inline ExtType_Bool(Category_Bool& p, Params<0>::Type params) : Type_Bool(p, params) {}--  ReturnTuple Call_default(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Bool.default")-    return ReturnTuple(Box_Bool(false));-  }--  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Bool.equals")-    const PrimBool Var_arg1 = (params_args.GetArg(0)).AsBool();-    const PrimBool Var_arg2 = (params_args.GetArg(1)).AsBool();-    return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));-  }--  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Bool.lessThan")-    const PrimBool Var_arg1 = (params_args.GetArg(0)).AsBool();-    const PrimBool Var_arg2 = (params_args.GetArg(1)).AsBool();-    return ReturnTuple(Box_Bool(!Var_arg1 && Var_arg2));-  }-};--ReturnTuple DispatchBool(PrimBool value, const ValueFunction& label,-                         const ParamsArgs& params_args) {-  switch (label.collection) {-    case CategoryId_AsBool:-      return ReturnTuple(Box_Bool(value));-    case CategoryId_AsFloat:-      return ReturnTuple(Box_Float(value ? 1.0 : 0.0));-    case CategoryId_AsInt:-      return ReturnTuple(Box_Int(value? 1 : 0));-    case CategoryId_Duplicate:-      return ReturnTuple(Box_Bool(value));-    case CategoryId_Formatted:-      return ReturnTuple(Box_String(value? "true" : "false"));-    case CategoryId_Hashed:-      return ReturnTuple(Box_Int(value ? 1000000009ULL : 1000000007ULL));-    default:-      FAIL() << "Bool does not implement " << label;-      __builtin_unreachable();-  }-}--Category_Bool& CreateCategory_Bool() {-  static auto& category = *new ExtCategory_Bool();-  return category;-}--S<const Type_Bool> CreateType_Bool(const Params<0>::Type& params) {-  static const auto cached = S_get(new ExtType_Bool(CreateCategory_Bool(), Params<0>::Type()));-  return cached;-}--void RemoveType_Bool(const Params<0>::Type& params) {}--#ifdef ZEOLITE_PUBLIC_NAMESPACE-}  // namespace ZEOLITE_PUBLIC_NAMESPACE-using namespace ZEOLITE_PUBLIC_NAMESPACE;-#endif  // ZEOLITE_PUBLIC_NAMESPACE
− base/src/Extension_Char.cpp
@@ -1,115 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2019-2022 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]--#include "category-source.hpp"-#include "Streamlined_Char.hpp"-#include "Category_AsBool.hpp"-#include "Category_AsChar.hpp"-#include "Category_AsFloat.hpp"-#include "Category_AsInt.hpp"-#include "Category_Bool.hpp"-#include "Category_Char.hpp"-#include "Category_Default.hpp"-#include "Category_Duplicate.hpp"-#include "Category_Equals.hpp"-#include "Category_Float.hpp"-#include "Category_Formatted.hpp"-#include "Category_Hashed.hpp"-#include "Category_Int.hpp"-#include "Category_LessThan.hpp"-#include "Category_String.hpp"--#ifdef ZEOLITE_PUBLIC_NAMESPACE-namespace ZEOLITE_PUBLIC_NAMESPACE {-#endif  // ZEOLITE_PUBLIC_NAMESPACE--struct ExtCategory_Char : public Category_Char {-};--struct ExtType_Char : public Type_Char {-  inline ExtType_Char(Category_Char& p, Params<0>::Type params) : Type_Char(p, params) {}--  ReturnTuple Call_maxBound(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Char.maxBound")-    return ReturnTuple(Box_Char('\xff'));-  }--  ReturnTuple Call_minBound(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Char.minBound")-    return ReturnTuple(Box_Char('\0'));-  }--  ReturnTuple Call_default(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Char.default")-    return ReturnTuple(Box_Char('\0'));-  }--  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Char.equals")-    const PrimChar Var_arg1 = (params_args.GetArg(0)).AsChar();-    const PrimChar Var_arg2 = (params_args.GetArg(1)).AsChar();-    return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));-  }--  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Char.lessThan")-    const PrimChar Var_arg1 = (params_args.GetArg(0)).AsChar();-    const PrimChar Var_arg2 = (params_args.GetArg(1)).AsChar();-    return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));-  }-};--ReturnTuple DispatchChar(PrimChar value, const ValueFunction& label,-                         const ParamsArgs& params_args) {-  switch (label.collection) {-    case CategoryId_AsBool:-      return ReturnTuple(Box_Bool(value != '\0'));-    case CategoryId_AsChar:-      return ReturnTuple(Box_Char(value));-    case CategoryId_AsFloat:-      return ReturnTuple(Box_Float(((int) value + 256) % 256));-    case CategoryId_AsInt:-      return ReturnTuple(Box_Int(((int) value + 256) % 256));-    case CategoryId_Duplicate:-      return ReturnTuple(Box_Char(value));-    case CategoryId_Formatted:-      return ReturnTuple(Box_String(PrimString(1, value)));-    case CategoryId_Hashed:-      return ReturnTuple(Box_Int(1000000009ULL * ((unsigned long long) value + 1000000007ULL)));-    default:-      FAIL() << "Char does not implement " << label;-      __builtin_unreachable();-  }-}--Category_Char& CreateCategory_Char() {-  static auto& category = *new ExtCategory_Char();-  return category;-}--S<const Type_Char> CreateType_Char(const Params<0>::Type& params) {-  static const auto cached = S_get(new ExtType_Char(CreateCategory_Char(), Params<0>::Type()));-  return cached;-}--void RemoveType_Char(const Params<0>::Type& params) {}--#ifdef ZEOLITE_PUBLIC_NAMESPACE-}  // namespace ZEOLITE_PUBLIC_NAMESPACE-using namespace ZEOLITE_PUBLIC_NAMESPACE;-#endif  // ZEOLITE_PUBLIC_NAMESPACE
− base/src/Extension_CharBuffer.cpp
@@ -1,115 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2019-2021 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]--#include "category-source.hpp"-#include "Streamlined_CharBuffer.hpp"-#include "Category_Char.hpp"-#include "Category_CharBuffer.hpp"-#include "Category_Container.hpp"-#include "Category_Int.hpp"-#include "Category_ReadAt.hpp"-#include "Category_WriteAt.hpp"--#ifdef ZEOLITE_PUBLIC_NAMESPACE-namespace ZEOLITE_PUBLIC_NAMESPACE {-#endif  // ZEOLITE_PUBLIC_NAMESPACE--BoxedValue CreateValue_CharBuffer(S<const Type_CharBuffer> parent, PrimCharBuffer buffer);--struct ExtCategory_CharBuffer : public Category_CharBuffer {-};--struct ExtType_CharBuffer : public Type_CharBuffer {-  inline ExtType_CharBuffer(Category_CharBuffer& p, Params<0>::Type params) : Type_CharBuffer(p, params) {}--  ReturnTuple Call_new(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("CharBuffer.new")-    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();-    if (Var_arg1 < 0) {-      FAIL() << "Buffer size " << Var_arg1 << " is invalid";-    }-    return ReturnTuple(CreateValue_CharBuffer(CreateType_CharBuffer(Params<0>::Type()), PrimCharBuffer(Var_arg1,'\0')));-  }-};--struct ExtValue_CharBuffer : public Value_CharBuffer {-  inline ExtValue_CharBuffer(S<const Type_CharBuffer> p, PrimCharBuffer value)-    : Value_CharBuffer(std::move(p)), value_(std::move(value)) {}--  ReturnTuple Call_readAt(const ParamsArgs& params_args) final {-    TRACE_FUNCTION("CharBuffer.readAt")-    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();-    if (Var_arg1 < 0 || Var_arg1 >= AsCharBuffer().size()) {-      FAIL() << "Read position " << Var_arg1 << " is out of bounds";-    }-    return ReturnTuple(Box_Char(AsCharBuffer()[Var_arg1]));-  }--  ReturnTuple Call_resize(const ParamsArgs& params_args) final {-    TRACE_FUNCTION("CharBuffer.resize")-    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();-    if (Var_arg1 < 0) {-      FAIL() << "Buffer size " << Var_arg1 << " is invalid";-    } else {-      value_.resize(Var_arg1);-    }-    return ReturnTuple(VAR_SELF);-  }--  ReturnTuple Call_size(const ParamsArgs& params_args) final {-    TRACE_FUNCTION("CharBuffer.size")-    return ReturnTuple(Box_Int(value_.size()));-  }--  ReturnTuple Call_writeAt(const ParamsArgs& params_args) final {-    TRACE_FUNCTION("CharBuffer.writeAt")-    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();-    const PrimChar Var_arg2 = (params_args.GetArg(1)).AsChar();-    if (Var_arg1 < 0 || Var_arg1 >= value_.size()) {-      FAIL() << "Write position " << Var_arg1 << " is out of bounds";-    } else {-      value_[Var_arg1] = Var_arg2;-    }-    return ReturnTuple(VAR_SELF);-  }--  PrimCharBuffer& AsCharBuffer() final { return value_; }--  PrimCharBuffer value_;-};--Category_CharBuffer& CreateCategory_CharBuffer() {-  static auto& category = *new ExtCategory_CharBuffer();-  return category;-}--S<const Type_CharBuffer> CreateType_CharBuffer(const Params<0>::Type& params) {-  static const auto cached = S_get(new ExtType_CharBuffer(CreateCategory_CharBuffer(), Params<0>::Type()));-  return cached;-}--void RemoveType_CharBuffer(const Params<0>::Type& params) {}--BoxedValue CreateValue_CharBuffer(S<const Type_CharBuffer> parent, PrimCharBuffer value) {-  return BoxedValue::New<ExtValue_CharBuffer>(std::move(parent), std::move(value));-}--#ifdef ZEOLITE_PUBLIC_NAMESPACE-}  // namespace ZEOLITE_PUBLIC_NAMESPACE-using namespace ZEOLITE_PUBLIC_NAMESPACE;-#endif  // ZEOLITE_PUBLIC_NAMESPACE
− base/src/Extension_Float.cpp
@@ -1,107 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2019-2022 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]--#include <sstream>--#include "category-source.hpp"-#include "Streamlined_Float.hpp"-#include "Category_AsBool.hpp"-#include "Category_AsFloat.hpp"-#include "Category_AsInt.hpp"-#include "Category_Bool.hpp"-#include "Category_Default.hpp"-#include "Category_Duplicate.hpp"-#include "Category_Equals.hpp"-#include "Category_Float.hpp"-#include "Category_Formatted.hpp"-#include "Category_Hashed.hpp"-#include "Category_Int.hpp"-#include "Category_LessThan.hpp"-#include "Category_String.hpp"--#ifdef ZEOLITE_PUBLIC_NAMESPACE-namespace ZEOLITE_PUBLIC_NAMESPACE {-#endif  // ZEOLITE_PUBLIC_NAMESPACE--struct ExtCategory_Float : public Category_Float {-};--struct ExtType_Float : public Type_Float {-  inline ExtType_Float(Category_Float& p, Params<0>::Type params) : Type_Float(p, params) {}--  ReturnTuple Call_default(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Float.default")-    return ReturnTuple(Box_Float(0.0));-  }--  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Float.equals")-    const PrimFloat Var_arg1 = (params_args.GetArg(0)).AsFloat();-    const PrimFloat Var_arg2 = (params_args.GetArg(1)).AsFloat();-    return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));-  }--  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Float.lessThan")-    const PrimFloat Var_arg1 = (params_args.GetArg(0)).AsFloat();-    const PrimFloat Var_arg2 = (params_args.GetArg(1)).AsFloat();-    return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));-  }-};--ReturnTuple DispatchFloat(PrimFloat value, const ValueFunction& label,-                          const ParamsArgs& params_args) {-  switch (label.collection) {-    case CategoryId_AsBool:-      return ReturnTuple(Box_Bool(value != 0.0));-    case CategoryId_AsFloat:-      return ReturnTuple(Box_Float(value));-    case CategoryId_AsInt:-      return ReturnTuple(Box_Int(value));-    case CategoryId_Duplicate:-      return ReturnTuple(Box_Float(value));-    case CategoryId_Formatted: {-      // NOTE: std::to_string does weird things with significant digits.-      std::ostringstream output;-      output << value;-      return ReturnTuple(Box_String(output.str()));-    }-    case CategoryId_Hashed:-      return ReturnTuple(Box_Int(1000000009ULL * reinterpret_cast<uint64_t&>(value)));-    default:-      FAIL() << "Float does not implement " << label;-      __builtin_unreachable();-  }-}--Category_Float& CreateCategory_Float() {-  static auto& category = *new ExtCategory_Float();-  return category;-}--S<const Type_Float> CreateType_Float(const Params<0>::Type& params) {-  static const auto cached = S_get(new ExtType_Float(CreateCategory_Float(), Params<0>::Type()));-  return cached;-}--void RemoveType_Float(const Params<0>::Type& params) {}--#ifdef ZEOLITE_PUBLIC_NAMESPACE-}  // namespace ZEOLITE_PUBLIC_NAMESPACE-using namespace ZEOLITE_PUBLIC_NAMESPACE;-#endif  // ZEOLITE_PUBLIC_NAMESPACE
− base/src/Extension_Int.cpp
@@ -1,118 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2019-2022 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]--#include <climits>-#include <string>--#include "category-source.hpp"-#include "Streamlined_Int.hpp"-#include "Category_AsBool.hpp"-#include "Category_AsChar.hpp"-#include "Category_AsFloat.hpp"-#include "Category_AsInt.hpp"-#include "Category_Bool.hpp"-#include "Category_Char.hpp"-#include "Category_Default.hpp"-#include "Category_Duplicate.hpp"-#include "Category_Equals.hpp"-#include "Category_Float.hpp"-#include "Category_Formatted.hpp"-#include "Category_Hashed.hpp"-#include "Category_Int.hpp"-#include "Category_LessThan.hpp"-#include "Category_String.hpp"--#ifdef ZEOLITE_PUBLIC_NAMESPACE-namespace ZEOLITE_PUBLIC_NAMESPACE {-#endif  // ZEOLITE_PUBLIC_NAMESPACE--struct ExtCategory_Int : public Category_Int {-};--struct ExtType_Int : public Type_Int {-  inline ExtType_Int(Category_Int& p, Params<0>::Type params) : Type_Int(p, params) {}--  ReturnTuple Call_maxBound(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Int.maxBound")-    return ReturnTuple(Box_Int(9223372036854775807LL));-  }--  ReturnTuple Call_minBound(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Int.minBound")-    return ReturnTuple(Box_Int(-9223372036854775807LL - 1LL));-  }--  ReturnTuple Call_default(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Int.default")-    return ReturnTuple(Box_Int(0));-  }--  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Int.equals")-    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();-    const PrimInt Var_arg2 = (params_args.GetArg(1)).AsInt();-    return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));-  }--  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("Int.lessThan")-    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();-    const PrimInt Var_arg2 = (params_args.GetArg(1)).AsInt();-    return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));-  }-};--ReturnTuple DispatchInt(PrimInt value, const ValueFunction& label,-                        const ParamsArgs& params_args) {-  switch (label.collection) {-    case CategoryId_AsBool:-      return ReturnTuple(Box_Bool(value != 0));-    case CategoryId_AsChar:-      return ReturnTuple(Box_Char(PrimChar(((value % 256) + 256) % 256)));-    case CategoryId_AsFloat:-      return ReturnTuple(Box_Float(value));-    case CategoryId_AsInt:-      return ReturnTuple(Box_Int(value));-    case CategoryId_Duplicate:-      return ReturnTuple(Box_Int(value));-    case CategoryId_Formatted:-      return ReturnTuple(Box_String(std::to_string(value)));-    case CategoryId_Hashed:-      return ReturnTuple(Box_Int(1000000007ULL * value));-    default:-      FAIL() << "Int does not implement " << label;-      __builtin_unreachable();-  }-}--Category_Int& CreateCategory_Int() {-  static auto& category = *new ExtCategory_Int();-  return category;-}--S<const Type_Int> CreateType_Int(const Params<0>::Type& params) {-  static const auto cached = S_get(new ExtType_Int(CreateCategory_Int(), Params<0>::Type()));-  return cached;-}--void RemoveType_Int(const Params<0>::Type& params) {}--#ifdef ZEOLITE_PUBLIC_NAMESPACE-}  // namespace ZEOLITE_PUBLIC_NAMESPACE-using namespace ZEOLITE_PUBLIC_NAMESPACE;-#endif  // ZEOLITE_PUBLIC_NAMESPACE
− base/src/Extension_Pointer.cpp
@@ -1,62 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2022 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]--#include "category-source.hpp"-#include "Streamlined_Pointer.hpp"--#ifdef ZEOLITE_PUBLIC_NAMESPACE-namespace ZEOLITE_PUBLIC_NAMESPACE {-#endif  // ZEOLITE_PUBLIC_NAMESPACE--struct ExtCategory_Pointer : public Category_Pointer {-};--struct ExtType_Pointer : public Type_Pointer {-  inline ExtType_Pointer(Category_Pointer& p, Params<1>::Type params) : Type_Pointer(p, params) {}-};--ReturnTuple DispatchPointer(PrimPointer value, const ValueFunction& label,-                            const ParamsArgs& params_args) {-  switch (label.collection) {-    default:-      FAIL() << "Pointer does not implement " << label;-      __builtin_unreachable();-  }-}--Category_Pointer& CreateCategory_Pointer() {-  static auto& category = *new ExtCategory_Pointer();-  return category;-}--static auto& Pointer_instance_cache = *new InstanceCache<1, Type_Pointer>([](const Params<1>::Type& params) {-    return S_get(new ExtType_Pointer(CreateCategory_Pointer(), params));-  });--S<const Type_Pointer> CreateType_Pointer(const Params<1>::Type& params) {-  return Pointer_instance_cache.GetOrCreate(params);-}--void RemoveType_Pointer(const Params<1>::Type& params) {-  Pointer_instance_cache.Remove(params);-}--#ifdef ZEOLITE_PUBLIC_NAMESPACE-}  // namespace ZEOLITE_PUBLIC_NAMESPACE-using namespace ZEOLITE_PUBLIC_NAMESPACE;-#endif  // ZEOLITE_PUBLIC_NAMESPACE
− base/src/Extension_String.cpp
@@ -1,228 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2019-2021 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]--#include "category-source.hpp"-#include "Streamlined_String.hpp"-#include "Category_Append.hpp"-#include "Category_AsBool.hpp"-#include "Category_Bool.hpp"-#include "Category_Build.hpp"-#include "Category_Char.hpp"-#include "Category_CharBuffer.hpp"-#include "Category_Container.hpp"-#include "Category_Default.hpp"-#include "Category_DefaultOrder.hpp"-#include "Category_Duplicate.hpp"-#include "Category_Equals.hpp"-#include "Category_Formatted.hpp"-#include "Category_Hashed.hpp"-#include "Category_Int.hpp"-#include "Category_LessThan.hpp"-#include "Category_Order.hpp"-#include "Category_ReadAt.hpp"-#include "Category_String.hpp"-#include "Category_SubSequence.hpp"--#ifdef ZEOLITE_PUBLIC_NAMESPACE-namespace ZEOLITE_PUBLIC_NAMESPACE {-#endif  // ZEOLITE_PUBLIC_NAMESPACE--struct ExtCategory_String : public Category_String {-};--class Value_StringBuilder : public TypeValue {- public:-  std::string CategoryName() const final { return "StringBuilder"; }--  ReturnTuple Dispatch(const ValueFunction& label,-                       const ParamsArgs& params_args) final {-    if (&label == &Function_Append_append) {-      TRACE_FUNCTION("StringBuilder.append")-      std::lock_guard<std::mutex> lock(mutex);-      output_ << TypeValue::Call(params_args.GetArg(0), Function_Formatted_formatted, PassParamsArgs()).At(0).AsString();-      return ReturnTuple(VAR_SELF);-    }-    if (&label == &Function_Build_build) {-      TRACE_FUNCTION("StringBuilder.build")-      std::lock_guard<std::mutex> lock(mutex);-      return ReturnTuple(Box_String(output_.str()));-    }-    return TypeValue::Dispatch(label, params_args);-  }-- private:-  std::mutex mutex;-  std::ostringstream output_;-};--struct ExtType_String : public Type_String {-  inline ExtType_String(Category_String& p, Params<0>::Type params) : Type_String(p, params) {}--  ReturnTuple Call_builder(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.builder")-    return ReturnTuple(BoxedValue::New<Value_StringBuilder>());-  }--  ReturnTuple Call_default(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.default")-    return ReturnTuple(Box_String(""));-  }--  ReturnTuple Call_equals(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.equals")-    const BoxedValue& Var_arg1 = (params_args.GetArg(0));-    const BoxedValue& Var_arg2 = (params_args.GetArg(1));-    return ReturnTuple(Box_Bool(Var_arg1.AsString()==Var_arg2.AsString()));-  }--  ReturnTuple Call_fromCharBuffer(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.fromCharBuffer")-    const BoxedValue& Var_arg1 = (params_args.GetArg(0));-    return ReturnTuple(Box_String(PrimString(Var_arg1.AsCharBuffer())));-  }--  ReturnTuple Call_lessThan(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.lessThan")-    const BoxedValue& Var_arg1 = (params_args.GetArg(0));-    const BoxedValue& Var_arg2 = (params_args.GetArg(1));-    return ReturnTuple(Box_Bool(Var_arg1.AsString()<Var_arg2.AsString()));-  }-};--class StringOrder : public TypeValue {- public:-  StringOrder(BoxedValue container, const std::string& s)-    : container_(container), value_(s) {}--  std::string CategoryName() const final { return "StringOrder"; }--  ReturnTuple Dispatch(const ValueFunction& label, const ParamsArgs& params_args) final {-    if (&label == &Function_Order_next) {-      TRACE_FUNCTION("StringOrder.next")-      if (index_+1 >= value_.size()) {-        return ReturnTuple(Var_empty);-      } else {-        ++index_;-        return ReturnTuple(VAR_SELF);-      }-    }-    if (&label == &Function_Order_get) {-      TRACE_FUNCTION("StringOrder.get")-      if (index_ >= value_.size()) {-        FAIL() << "Iterated past end of String";-      }-      return ReturnTuple(Box_Char(value_[index_]));-    }-    return TypeValue::Dispatch(label, params_args);-  }-- private:-  const BoxedValue container_;-  const std::string& value_;-  int index_ = 0;-};--struct ExtValue_String : public Value_String {-  inline ExtValue_String(S<const Type_String> p, const PrimString& value)-    : Value_String(std::move(p)), value_(value) {}--  ReturnTuple Call_asBool(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.asBool")-    return ReturnTuple(Box_Bool(value_.size() != 0));-  }--  ReturnTuple Call_defaultOrder(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.defaultOrder")-    if (value_.empty()) {-      return ReturnTuple(Var_empty);-    } else {-      return ReturnTuple(BoxedValue::New<StringOrder>(VAR_SELF, value_));-    }-  }--  ReturnTuple Call_duplicate(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.duplicate")-    return ReturnTuple(VAR_SELF);-  }--  ReturnTuple Call_formatted(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.formatted")-    return ReturnTuple(VAR_SELF);-  }--  ReturnTuple Call_hashed(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.hashed")-    PrimInt hash = 1000000009ULL;-    for (char c : value_) {-      hash = hash * 1000000009ULL + (unsigned long long) c * 1000000007ULL;-    }-    return ReturnTuple(Box_Int(hash));-  }--  ReturnTuple Call_readAt(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.readAt")-    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();-    if (Var_arg1 < 0 || Var_arg1 >= value_.size()) {-      FAIL() << "Read position " << Var_arg1 << " is out of bounds";-    }-    return ReturnTuple(Box_Char(value_[Var_arg1]));-  }--  ReturnTuple Call_size(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.size")-    return ReturnTuple(Box_Int(value_.size()));-  }--  ReturnTuple Call_subSequence(const ParamsArgs& params_args) const final {-    TRACE_FUNCTION("String.subSequence")-    const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();-    const PrimInt Var_arg2 = (params_args.GetArg(1)).AsInt();-    if (Var_arg1 < 0 || Var_arg1 > value_.size()) {-      FAIL() << "Subsequence position " << Var_arg1 << " is out of bounds";-    }-    if (Var_arg2 < 0 || Var_arg1 + Var_arg2 > value_.size()) {-      FAIL() << "Subsequence size " << Var_arg2 << " is invalid";-    }-    return ReturnTuple(Box_String(value_.substr(Var_arg1,Var_arg2)));-  }--  const PrimString& AsString() const final { return value_; }--  const PrimString value_;-};--Category_String& CreateCategory_String() {-  static auto& category = *new ExtCategory_String();-  return category;-}--S<const Type_String> CreateType_String(const Params<0>::Type& params) {-  static const auto cached = S_get(new ExtType_String(CreateCategory_String(), Params<0>::Type()));-  return cached;-}--void RemoveType_String(const Params<0>::Type& params) {}--#ifdef ZEOLITE_PUBLIC_NAMESPACE-}  // namespace ZEOLITE_PUBLIC_NAMESPACE-using namespace ZEOLITE_PUBLIC_NAMESPACE;-#endif  // ZEOLITE_PUBLIC_NAMESPACE--BoxedValue Box_String(const PrimString& value) {-  return BoxedValue::New<ExtValue_String>(CreateType_String(Params<0>::Type()), value);-}
base/src/boxed.cpp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021-2022 Kevin P. Barry+Copyright 2021-2023 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.@@ -42,6 +42,11 @@ ReturnTuple DispatchPointer(PrimPointer value, const ValueFunction& label,                             const ParamsArgs& params_args) __attribute__((weak)); +ReturnTuple DispatchIdentifier(PrimIdentifier value, const ValueFunction& label,+                             const ParamsArgs& params_args) __attribute__((weak));++PrimIdentifier RandomizeIdentifier(PrimIdentifier identifier) __attribute__((weak));+ #ifdef ZEOLITE_PUBLIC_NAMESPACE }  // namespace ZEOLITE_PUBLIC_NAMESPACE using namespace ZEOLITE_PUBLIC_NAMESPACE;@@ -83,12 +88,13 @@  std::string UnionValue::CategoryName() const {   switch (type_) {-    case UnionValue::Type::EMPTY:   return "empty";-    case UnionValue::Type::BOOL:    return "Bool";-    case UnionValue::Type::CHAR:    return "Char";-    case UnionValue::Type::INT:     return "Int";-    case UnionValue::Type::FLOAT:   return "Float";-    case UnionValue::Type::POINTER: return "Pointer";+    case UnionValue::Type::EMPTY:      return "empty";+    case UnionValue::Type::BOOL:       return "Bool";+    case UnionValue::Type::CHAR:       return "Char";+    case UnionValue::Type::INT:        return "Int";+    case UnionValue::Type::FLOAT:      return "Float";+    case UnionValue::Type::POINTER:    return "Pointer";+    case UnionValue::Type::IDENTIFIER: return "Identifier";     case UnionValue::Type::BOXED:       if (!value_.as_boxed_ || !value_.as_boxed_->object_) {         FAIL() << "Function called on null pointer";@@ -120,6 +126,16 @@   zeolite_internal::Validate(name, union_); } +// static+PrimIdentifier BoxedValue::Identify(const BoxedValue& target) {+  switch (target.union_.type_) {+    case UnionValue::Type::IDENTIFIER:+      return target.union_.value_.as_identifier_;+    default:+      return RandomizeIdentifier(target.union_.value_.as_identifier_);+  }+}+ const PrimString& BoxedValue::AsString() const {   switch (union_.type_) {     case UnionValue::Type::BOXED:@@ -165,6 +181,8 @@       return DispatchFloat(union_.value_.as_float_, label, params_args);     case UnionValue::Type::POINTER:       return DispatchPointer(union_.value_.as_pointer_, label, params_args);+    case UnionValue::Type::IDENTIFIER:+      return DispatchIdentifier(union_.value_.as_identifier_, label, params_args);     case UnionValue::Type::BOXED:       if (!union_.value_.as_boxed_ || !union_.value_.as_boxed_->object_) {         FAIL() << "Function called on null pointer";
base/src/category-source.cpp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -269,4 +269,43 @@ PrimCharBuffer& TypeValue::AsCharBuffer() {   FAIL() << CategoryName() << " is not a CharBuffer value";   __builtin_unreachable();+}++namespace {++class CallTrace : public TypeValue {+ public:+  CallTrace(BoxedValue next, std::string trace, const ValueFunction& get_func, const ValueFunction& next_func)+    : next_(std::move(next)), trace_(std::move(trace)), next_func_(next_func), get_func_(get_func) {}++  std::string CategoryName() const override {+    return "CallTrace";+  }++  ReturnTuple Dispatch(const ValueFunction& label, const ParamsArgs& params_args) override {+    if (&label == &next_func_) {+      return ReturnTuple(next_);+    }+    if (&label == &get_func_) {+      return ReturnTuple(Box_String(trace_));+    }+    return TypeValue::Dispatch(label, params_args);+  }++ private:+  const BoxedValue next_;+  const std::string trace_;+  const ValueFunction& get_func_;+  const ValueFunction& next_func_;+};++}  // namespace++BoxedValue GetCallTrace(const ValueFunction& get_func, const ValueFunction& next_func) {+  const TraceList trace = TraceContext::GetTrace();+  BoxedValue head;+  for (auto current = trace.rbegin(), end = trace.rend(); current != end; ++current) {+    head = BoxedValue::New<CallTrace>(head, (*current)(), get_func, next_func);+  }+  return head; }
+ base/src/cleanup.cpp view
@@ -0,0 +1,53 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++#include "cleanup.hpp"++#include "category-source.hpp"+++// static+void GlobalCleanup::Finish(int code) {+  GlobalCleanup* current = GetCurrent();+  while (current) {+    current->Cleanup(code);+    current = current->GetNext();+  }+}++WrapTypeCall::WrapTypeCall(S<const TypeInstance> type, const TypeFunction* start, const TypeFunction* finish)+  : type_(std::move(type)), finish_(finish), cross_and_capture_to_(this) {+  if (start) {+    (void) TypeInstance::Call(type_, *start, PassParamsArgs());+  }+}++WrapTypeCall::~WrapTypeCall() {+  Cleanup(0);+}++GlobalCleanup* WrapTypeCall::GetNext() const {+  return cross_and_capture_to_.Previous();+}++void WrapTypeCall::Cleanup(int code) {+  if (finish_) {+    (void) TypeInstance::Call(type_, *finish_, PassParamsArgs());+    finish_ = nullptr;+  }+}
+ base/testing.0rp view
@@ -0,0 +1,25 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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$++// Used for automating checks for a testcase.+@type interface Testcase {+  start () -> ()+  finish () -> ()+}
base/types.hpp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -47,6 +47,45 @@ class OpaqueObject { ~OpaqueObject() = default; }; using PrimPointer = OpaqueObject*; +class OpaqueInstance { ~OpaqueInstance() = default; };+using PrimIdentifier = OpaqueInstance*;++inline void SwapValues(PrimBool& left, PrimBool& right) {+  PrimBool temp = right;+  right = left;+  left = temp;+}++inline void SwapValues(PrimInt& left, PrimInt& right) {+  PrimInt temp = right;+  right = left;+  left = temp;+}++inline void SwapValues(PrimChar& left, PrimChar& right) {+  PrimChar temp = right;+  right = left;+  left = temp;+}++inline void SwapValues(PrimFloat& left, PrimFloat& right) {+  PrimFloat temp = right;+  right = left;+  left = temp;+}++inline void SwapValues(PrimPointer& left, PrimPointer& right) {+  PrimPointer temp = right;+  right = left;+  left = temp;+}++inline void SwapValues(PrimIdentifier& left, PrimIdentifier& right) {+  PrimIdentifier temp = right;+  right = left;+  left = temp;+}+ template<int S> inline PrimString PrimString_FromLiteral(const char(&literal)[S]) {   return PrimString(literal, literal + (S - 1));@@ -96,6 +135,12 @@     return *this;   } +  LazyInit& operator = (T&& value) {+    InitValue();+    value_ = value;+    return *this;+  }+  private:   LazyInit(const LazyInit&) = delete;   LazyInit(LazyInit&&) = delete;@@ -118,6 +163,27 @@   T value_;   const std::function<T()> create_; };++template<class T>+inline void SwapValues(LazyInit<T>& left, LazyInit<T>& right) {+  T temp = right.Get();+  right = left.Get();+  left = std::move(temp);+}++template<class T>+inline void SwapValues(T& left, LazyInit<T>& right) {+  T temp = right.Get();+  right = std::move(left);+  left = std::move(temp);+}++template<class T>+inline void SwapValues(LazyInit<T>& left, T& right) {+  T temp = std::move(right);+  right = left.Get();+  left = std::move(temp);+}   class TypeCategory;
bin/zeolite-setup.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2020-2021 Kevin P. Barry+Copyright 2020-2021,2023 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.@@ -40,6 +40,7 @@                           then handle pn os                           else compilerErrorM "Parallel processes (-j) must be > 0."           _ -> compilerErrorM "Parallel processes (-j) must be > 0."+  handle pn (('-':'j':n@(_:_)):os) = handle pn ("-j":n:os)   handle pn ("--reuse":_) = do     config <- loadConfig     runWith pn config@@ -68,13 +69,13 @@ libraries :: [String] libraries = [     "base",+    "tests",     "lib/testing",     "lib/util",     "lib/container",     "lib/file",     "lib/math",-    "lib/thread",-    "tests"+    "lib/thread"   ]  optionalLibraries :: [String]@@ -173,6 +174,8 @@       _coForce = ForceAll,       _coParallel = pn     }-  runCompiler resolver backend options+  -- The 2 lines below suppress warnings if there were no errors.+  result <- lift $ toTrackedErrors $ runCompiler resolver backend options+  when (isCompilerError result) (fromTrackedErrors result)   mapM_ optionalWarning optionalLibraries where   optionalWarning library = compilerWarningM $ "Optional library " ++ library ++ " must be built manually if needed"
example/parser/.zeolite-module view
@@ -7,4 +7,4 @@   "lib/file"   "lib/testing" ]-mode: incremental {}+mode: incremental { }
example/parser/parse-text.0rp view
@@ -5,7 +5,7 @@  // Parses a string containing a limited set of characters. concrete SequenceOfParser {-  @type create (String, Int /*min*/, Int /*max*/) -> (Parser<String>)+  @type create (String, Int min:, Int max:) -> (Parser<String>) }  // Parses a fixed character.@@ -21,7 +21,7 @@    @type error     (Formatted)              -> (Parser<all>)   @type try<#x>   (Parser<#x>)             -> (Parser<#x>)-  @type or<#x>    (Parser<#x>,Parser<#x>)  -> (Parser<#x>)-  @type left<#x>  (Parser<#x>,Parser<any>) -> (Parser<#x>)-  @type right<#x> (Parser<any>,Parser<#x>) -> (Parser<#x>)+  @type or<#x>    (Parser<#x>, Parser<#x>)  -> (Parser<#x>)+  @type left<#x>  (Parser<#x>, Parser<any>) -> (Parser<#x>)+  @type right<#x> (Parser<any>, Parser<#x>) -> (Parser<#x>) }
example/parser/parse-text.0rx view
@@ -25,7 +25,7 @@   }    create (match) {-    return StringParser{ match }+    return delegate -> #self   } } @@ -44,7 +44,7 @@                       min.formatted() + "," + max.formatted() + "} at " +                       contextOld.getPosition()     ParseContext<any> context <- contextOld-    [Append<Formatted>&Build<String>] builder <- String.builder()+    [Append<Formatted> & Build<String>] builder <- String.builder()      optional Order<Int> counter <- defer     if (max == 0) {@@ -55,13 +55,13 @@      Int count <- 0     traverse (counter -> count) {-      $Hidden[count,counter]$+      $Hidden[count, counter]$       if (context.atEof()) {         break       }       Bool found <- false       traverse (Counter.zeroIndexed(matches.size()) -> Int index) {-        $ReadOnly[context,index]$+        $ReadOnly[context, index]$         if (context.current() == matches.readAt(index)) {           \ builder.append(matches.readAt(index))           found <- true@@ -83,8 +83,8 @@     }   } -  create (matches,min,max) {-    return SequenceOfParser{ matches, min, max }+  create (matches, min, max) {+    return delegate -> #self   } } @@ -106,7 +106,7 @@   }    create (match) {-    return CharParser{ match }+    return delegate -> #self   } } @@ -126,7 +126,7 @@   }    create (value) {-    return #self{ value }+    return delegate -> #self   } } @@ -170,12 +170,12 @@   }    create (parser) {-    return #self{ parser }+    return delegate -> #self   } }  concrete OrParser<#x> {-  @type create (Parser<#x>,Parser<#x>) -> (Parser<#x>)+  @type create (Parser<#x>, Parser<#x>) -> (Parser<#x>) }  define OrParser {@@ -196,14 +196,14 @@     }   } -  create (parser1,parser2) {-    return #self{ parser1, parser2 }+  create (parser1, parser2) {+    return delegate -> #self   } }  concrete LeftParser<#x> { -  @type create (Parser<#x>,Parser<any>) -> (Parser<#x>)+  @type create (Parser<#x>, Parser<any>) -> (Parser<#x>) }  define LeftParser {@@ -229,13 +229,13 @@     }   } -  create (parser1,parser2) {-    return #self{ parser1, parser2 }+  create (parser1, parser2) {+    return delegate -> #self   } }  concrete RightParser<#x> {-  @type create (Parser<any>,Parser<#x>) -> (Parser<#x>)+  @type create (Parser<any>, Parser<#x>) -> (Parser<#x>) }  define RightParser {@@ -256,33 +256,33 @@     }   } -  create (parser1,parser2) {-    return #self{ parser1, parser2 }+  create (parser1, parser2) {+    return delegate -> #self   } }  define Parse {   error (message) {-    return ErrorParser.create(message)+    return delegate -> `ErrorParser.create`   }    const (value) {-    return ConstParser<#x>.create(value)+    return delegate -> `ConstParser<#x>.create`   }    try (parser) {-    return TryParser<#x>.create(parser)+    return delegate -> `TryParser<#x>.create`   } -  or (parser1,parser2) {-    return OrParser<#x>.create(parser1,parser2)+  or (parser1, parser2) {+    return delegate -> `OrParser<#x>.create`   } -  left (parser1,parser2) {-    return LeftParser<#x>.create(parser1,parser2)+  left (parser1, parser2) {+    return delegate -> `LeftParser<#x>.create`   } -  right (parser1,parser2) {-    return RightParser<#x>.create(parser1,parser2)+  right (parser1, parser2) {+    return delegate -> `RightParser<#x>.create`   } }
example/parser/parser-test.0rt view
@@ -1,13 +1,30 @@ testcase "parse data from a file" {-  success+  // We need to specify TestChecker here in order to use lib/testing.+  success TestChecker }  unittest test {   String raw <- FileTesting.forceReadFile($ExprLookup[MODULE_PATH]$ + "/test-data.txt")-  ErrorOr<TestData> errorOrData <- TestDataParser.create() `ParseState:consumeAll` raw-  TestData data <- errorOrData.getValue()+  ErrorOr<TestData> actual <- TestDataParser.create() `ParseState:consumeAll` raw -  \ Testing.checkEquals(data.getName(),"example data")-  \ Testing.checkEquals(data.getDescription(),"THIS_IS_A_TOKEN")-  \ Testing.checkFalse(data.getBoolean())+  // Since TestData.create specifies labels, we _must_ use them here.+  TestData expected <- TestData.create(+      name:        "example data",+      description: "THIS_IS_A_TOKEN",+      boolean:     false)++  // Since TestData refines TestCompare<TestData>, we can use Matches:value.+  \ actual.tryValue() `Matches:value` expected++  // If we want to check the ErrorOr<TestData> itself, we need a+  // ValueMatcher<TestData> to pass to CheckErrorOr:value. We can do this with+  // CheckValue:using to create one from TestCompare<TestData>.+  \ actual `Matches:with` CheckErrorOr:value(CheckValue:using(expected))++  // Matches:with uses more general matchers such as CheckValue:equals. &. below+  // will call the function iff the value isn't empty. This is needed in order+  // to call functions on optional values.+  \ actual.tryValue()&.name()        `Matches:with` CheckValue:equals("example data")+  \ actual.tryValue()&.description() `Matches:with` CheckValue:equals("THIS_IS_A_TOKEN")+  \ actual.tryValue()&.boolean()     `Matches:with` CheckValue:equals(false) }
example/parser/parser.0rp view
@@ -6,7 +6,7 @@ // ParseState<all> can convert to all other ParseState. concrete ParseState<|#x> {   // Consumes all input and returns the result.-  @category consumeAll<#y> (Parser<#y>,String) -> (ErrorOr<#y>)+  @category consumeAll<#y> (Parser<#y>, String) -> (ErrorOr<#y>) }  // A self-contained parser operation.@@ -26,7 +26,7 @@ @value interface ParseContext<|#x> {   // Continue computation.   run<#y>       (Parser<#y>) -> (ParseContext<#y>)-  runAndGet<#y> (Parser<#y>) -> (ParseContext<any>,ErrorOr<#y>)+  runAndGet<#y> (Parser<#y>) -> (ParseContext<any>, ErrorOr<#y>)   getValue      ()           -> (ErrorOr<#x>)    // End computation and pass on the next state.
example/parser/parser.0rx view
@@ -8,7 +8,7 @@   @value ErrorOr<#x>        value   @value optional Formatted error -  consumeAll (parser,data) {+  consumeAll (parser, data) {     ParseContext<#y> context <- parser.run(new(data))     if (context.hasAnyError()) {       return context.getValue()
example/parser/test-data.0rp view
@@ -1,12 +1,23 @@+// $TestsOnly$ means that categories in this file are only available in .0rt and+// in other files that use $TestsOnly$. $TestsOnly$  // A contrived object for test data. concrete TestData {-  @type create (String,String,Bool) -> (TestData)+  // This is used in tests. This allows fine-grained error information, vs. just+  // comparing the entire object for equality. (Also see parser-test.0rt.)+  refines TestCompare<TestData> -  @value getName        () -> (String)-  @value getDescription () -> (String)-  @value getBoolean     () -> (Bool)+  @value name        () -> (String)+  @value description () -> (String)+  @value boolean     () -> (Bool)++  // This limits visibility of everything below. In this case, we don't want+  // anyone besides TestDataParser (and unittest) to construct TestData.+  visibility TestDataParser++  // We can give arguments labels to require calls to be clearer.+  @type create (String name:, String description:, Bool boolean:) -> (TestData) }  
example/parser/test-data.0rx view
@@ -5,21 +5,38 @@   @value String description   @value Bool   boolean -  create (name,description,boolean) {+  create (name, description, boolean) {     return TestData{ name, description, boolean }   } -  getName () {+  name () {     return name   } -  getDescription () {+  description () {     return description   } -  getBoolean () {+  boolean () {     return boolean   }++  // From TestCompare<TestData>.+  testCompare (actual, report) {+    \ MultiChecker.new(report)+        .tryCheck(+            title: "name",+            actual.name(),+            CheckValue:equals(name))+        .tryCheck(+            title: "description",+            actual.description(),+            CheckValue:equals(description))+        .tryCheck(+            title: "boolean",+            actual.boolean(),+            CheckValue:equals(boolean))+  } }  define TestDataParser {@@ -38,16 +55,16 @@    refines Parser<TestData> -  @category Parser<any> whitespace <- SequenceOfParser.create(" \n\t",1,0) `Parse.or` Parse.error("Expected whitespace")+  @category Parser<any> whitespace <- SequenceOfParser.create(" \n\t", min: 1, max: 0) `Parse.or` Parse.error("Expected whitespace")    @category String sentenceChars <- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +                                     "abcdefghijklmnopqrstuvwxyz" +                                     "., !?-"-  @category Parser<String> sentence <- SequenceOfParser.create(sentenceChars,0,0)+  @category Parser<String> sentence <- SequenceOfParser.create(sentenceChars, min: 0, max: 0)   @category Parser<any>    quote    <- CharParser.create('"')    @category Parser<String> quotedSentence  <- quote `Parse.right` sentence `Parse.left` quote-  @category Parser<String> token           <- SequenceOfParser.create("ABCDEFGHIJKLMNOPQRSTUVWXYZ_",1,0)+  @category Parser<String> token           <- SequenceOfParser.create("ABCDEFGHIJKLMNOPQRSTUVWXYZ_", min: 1, max: 0)   @category Parser<String> sentenceOrToken <- quotedSentence `Parse.or` token `Parse.left` whitespace    @category Parser<Bool> acronym           <- StringParser.create("acronym")  `Parse.right` Parse.const(true)@@ -75,13 +92,15 @@       return context.convertError()     } else {       return context.setValue(-        ErrorOr:value(TestData.create(name.getValue(),-                                         description.getValue(),-                                         boolean.getValue())))+        // Since TestData.create specifies labels, we _must_ use them here.+        ErrorOr:value(TestData.create(+            name:        name.getValue(),+            description: description.getValue(),+            boolean:     boolean.getValue())))     }   }    create ()  {-    return TestDataParser{ }+    return delegate -> #self   } }
example/primes/flag.0rx view
@@ -1,5 +1,5 @@ define ThreadFlag {-  @value [ConditionWait&ConditionResume] cond+  @value [ConditionWait & ConditionResume] cond   @value Bool enabled   @value Bool canceled 
example/primes/prime-thread.0rp view
@@ -4,5 +4,5 @@ concrete PrimeThread {   refines Routine -  @type create (ThreadContinue,PrimeTracker) -> (PrimeThread)+  @type create (ThreadContinue, PrimeTracker) -> (PrimeThread) }
example/primes/prime-thread.0rx view
@@ -2,8 +2,8 @@   @value ThreadContinue flag   @value PrimeTracker   tracker -  create (flag,tracker) {-    return PrimeThread{ flag, tracker }+  create (flag, tracker) {+    return delegate -> #self   }    run () {
example/primes/primes-demo.0rx view
@@ -6,14 +6,14 @@   run () {     PrimeTracker tracker <- PrimeTracker.create()     ThreadFlag flag <- ThreadFlag.new()-    Thread thread <- ProcessThread.from(PrimeThread.create(flag,tracker)).start()+    Thread thread <- ProcessThread.from(PrimeThread.create(flag, tracker)).start()      // Interactive input loop.      scoped {       TextReader reader <- TextReader.fromBlockReader(BasicInput.stdin())     } in while (!reader.pastEnd()) {-      $Hidden[tracker,thread]$+      $Hidden[tracker, thread]$        \ BasicOutput.stderr()           .writeNow("Press [Enter] to toggle start/stop computation thread. Type \"exit\" to exit.\n")
example/random/random-demo.0rx view
@@ -15,35 +15,35 @@     // NOTE: The overall scale here doesn't matter; it just matters what the     // relative weights are. CategoricalTree only supports positive Int weights.     CategoricalTree<Char> weights <- CategoricalTree<Char>.new()-        .setWeight('a',8167)-        .setWeight('b',1492)-        .setWeight('c',2782)-        .setWeight('d',4253)-        .setWeight('e',12702)-        .setWeight('f',2228)-        .setWeight('g',2015)-        .setWeight('h',6094)-        .setWeight('i',6966)-        .setWeight('j',153)-        .setWeight('k',772)-        .setWeight('l',4025)-        .setWeight('m',2406)-        .setWeight('n',6749)-        .setWeight('o',7507)-        .setWeight('p',1929)-        .setWeight('q',95)-        .setWeight('r',5987)-        .setWeight('s',6327)-        .setWeight('t',9056)-        .setWeight('u',2758)-        .setWeight('v',978)-        .setWeight('w',2361)-        .setWeight('x',150)-        .setWeight('y',1974)-        .setWeight('z',74)+        .setWeight('a', 8167)+        .setWeight('b', 1492)+        .setWeight('c', 2782)+        .setWeight('d', 4253)+        .setWeight('e', 12702)+        .setWeight('f', 2228)+        .setWeight('g', 2015)+        .setWeight('h', 6094)+        .setWeight('i', 6966)+        .setWeight('j', 153)+        .setWeight('k', 772)+        .setWeight('l', 4025)+        .setWeight('m', 2406)+        .setWeight('n', 6749)+        .setWeight('o', 7507)+        .setWeight('p', 1929)+        .setWeight('q', 95)+        .setWeight('r', 5987)+        .setWeight('s', 6327)+        .setWeight('t', 9056)+        .setWeight('u', 2758)+        .setWeight('v', 978)+        .setWeight('w', 2361)+        .setWeight('x', 150)+        .setWeight('y', 1974)+        .setWeight('z', 74)      Generator<Char>  letter <- weights `RandomCategorical:sampleWith` RandomUniform.probability()-    Generator<Float> length <- RandomGaussian.new(5.0,3.0)+    Generator<Float> length <- RandomGaussian.new(5.0, 3.0)     Generator<Float> timing <- RandomExponential.new(4.0)      while (timeLimit <= 0.0 || Realtime.monoSeconds() < startTime+timeLimit) {@@ -56,7 +56,7 @@        // Populate the letters using their relative frequencies.       traverse (Counter.zeroIndexed(buffer.size()) -> Int pos) {-        \ buffer.writeAt(pos,letter.generate())+        \ buffer.writeAt(pos, letter.generate())       }        // Print the word.
lib/container/.zeolite-module view
@@ -34,4 +34,4 @@     categories: [Vector]   } ]-mode: incremental {}+mode: incremental { }
lib/container/auto-tree.0rp view
@@ -33,12 +33,12 @@ //   of the tree. It is provided as a filter for the return of getRoot() so that //   a container can implement custom functionality using the tree's structure //   without risking modification of the tree.-concrete AutoBinaryTree<|#n,#k,#v|#r> {+concrete AutoBinaryTree<|#n, #k, #v|#r> {   refines Container   refines Duplicate   #k immutable-  #n defines  KVFactory<#k,#v>-  #n requires BalancedTreeNode<#n,#k,#v>+  #n defines  KVFactory<#k, #v>+  #n requires BalancedTreeNode<#n, #k, #v>   #n requires Duplicate   #k defines  LessThan<#k>   #r allows   #n@@ -57,21 +57,21 @@   // Notes:   // - updateNode() will be called on every affected node, starting with the   //   deepest node. It might be called an arbitrary number of times per node.-  @value weakSet (#k,#v) -> (#v)+  @value weakSet (#k, #v) -> (#v)    // Swap the value associated with the key if it is not present.   //   // Notes:   // - updateNode() will be called on every affected node, starting with the   //   deepest node. It might be called an arbitrary number of times per node.-  @value swap (#k,optional #v) -> (optional #v)+  @value swap (#k, optional #v) -> (optional #v) }  // An interface for reading the state of a BST node. // // Notes: // - This is intended for internal use in BST-based categories.-@value interface BinaryTreeNode<|#k,#v> {+@value interface BinaryTreeNode<|#k, #v> {   getLower  () -> (optional #self)   getHigher () -> (optional #self)   getKey    () -> (#k)@@ -83,8 +83,8 @@ // // Notes: // - This is intended for internal use in BST-based categories.-@value interface BalancedTreeNode<#n|#k,#v|> {-  refines BinaryTreeNode<#k,#v>+@value interface BalancedTreeNode<#n|#k, #v|> {+  refines BinaryTreeNode<#k, #v>    // Set the lower child of the node.   //@@ -119,26 +119,26 @@ // // Notes: // - This is intended for internal use in BST-based categories.-concrete ForwardTreeOrder<|#k,#v> {-  refines Order<KeyValue<#k,#v>>+concrete ForwardTreeOrder<|#k, #v> {+  refines Order<KeyValue<#k, #v>> -  @category create<#k,#v> (optional BinaryTreeNode<#k,#v>) -> (optional ForwardTreeOrder<#k,#v>)+  @category create<#k, #v> (optional BinaryTreeNode<#k, #v>) -> (optional ForwardTreeOrder<#k, #v>) -  @category seek<#k,#v>+  @category seek<#k, #v>     #k defines LessThan<#k>-  (#k,optional BinaryTreeNode<#k,#v>) -> (optional ForwardTreeOrder<#k,#v>)+  (#k, optional BinaryTreeNode<#k, #v>) -> (optional ForwardTreeOrder<#k, #v>) }  // Provides reverse iteration of the nodes in a BST. // // Notes: // - This is intended for internal use in BST-based categories.-concrete ReverseTreeOrder<|#k,#v> {-  refines Order<KeyValue<#k,#v>>+concrete ReverseTreeOrder<|#k, #v> {+  refines Order<KeyValue<#k, #v>> -  @category create<#k,#v> (optional BinaryTreeNode<#k,#v>) -> (optional ReverseTreeOrder<#k,#v>)+  @category create<#k, #v> (optional BinaryTreeNode<#k, #v>) -> (optional ReverseTreeOrder<#k, #v>) -  @category seek<#k,#v>+  @category seek<#k, #v>     #k defines LessThan<#k>-  (#k,optional BinaryTreeNode<#k,#v>) -> (optional ReverseTreeOrder<#k,#v>)+  (#k, optional BinaryTreeNode<#k, #v>) -> (optional ReverseTreeOrder<#k, #v>) }
lib/container/hashed-map.0rp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -21,16 +21,17 @@ // Params: // - #k: The key type. // - #v: The value type.-concrete HashedMap<#k,#v> {+concrete HashedMap<#k, #v> {   defines Default   refines Container-  refines DefaultOrder<KeyValue<#k,#v>>+  refines DefaultOrder<KeyValue<#k, #v>>   refines Duplicate   refines KeyOrder<#k>-  refines KVExchange<#k,#v>-  refines KVWriter<#k,#v>-  refines KVReader<#k,#v>+  refines KVExchange<#k, #v>+  refines KVWriter<#k, #v>+  refines KVReader<#k, #v>   refines ValueOrder<#v>+  refines SetReader<#k>   #k immutable   #k defines Equals<#k>   #k requires Hashed
lib/container/helpers.0rp view
@@ -30,10 +30,10 @@   // Example:   //   //   Bool lt <- x `KeyValueH:lessThan` y-  @category lessThan<#k,#v>+  @category lessThan<#k, #v>     #k defines LessThan<#k>     #v defines LessThan<#v>-  (KeyValue<#k,#v>,KeyValue<#k,#v>) -> (Bool)+  (KeyValue<#k, #v>, KeyValue<#k, #v>) -> (Bool)    // The same as lessThan, but with custom comparators.   //@@ -49,11 +49,11 @@   // Example:   //   //   // Ignore the value and compare Int keys.-  //   Bool lt <- x `KeyValueH:lessThanWith<?,?,Int,AlwaysEqual>` y-  @category lessThanWith<#k,#v,#kk,#vv>+  //   Bool lt <- x `KeyValueH:lessThanWith<?, ?, Int, AlwaysEqual>` y+  @category lessThanWith<#k, #v, #kk, #vv>     #kk defines LessThan<#k>     #vv defines LessThan<#v>-  (KeyValue<#k,#v>,KeyValue<#k,#v>) -> (Bool)+  (KeyValue<#k, #v>, KeyValue<#k, #v>) -> (Bool)    // Compare for equals.   //@@ -64,10 +64,10 @@   // Example:   //   //   Bool eq <- x `KeyValueH:equals` y-  @category equals<#k,#v>+  @category equals<#k, #v>     #k defines Equals<#k>     #v defines Equals<#v>-  (KeyValue<#k,#v>,KeyValue<#k,#v>) -> (Bool)+  (KeyValue<#k, #v>, KeyValue<#k, #v>) -> (Bool)    // The same as equals, but with custom comparators.   //@@ -80,9 +80,9 @@   // Example:   //   //   // Ignore the key and compare Int values.-  //   Bool eq <- x `KeyValueH:equalsWith<?,?,AlwaysEqual,Int>` y-  @category equalsWith<#k,#v,#kk,#vv>+  //   Bool eq <- x `KeyValueH:equalsWith<?, ?, AlwaysEqual, Int>` y+  @category equalsWith<#k, #v, #kk, #vv>     #kk defines Equals<#k>     #vv defines Equals<#v>-  (KeyValue<#k,#v>,KeyValue<#k,#v>) -> (Bool)+  (KeyValue<#k, #v>, KeyValue<#k, #v>) -> (Bool) }
lib/container/interfaces.0rp view
@@ -48,9 +48,9 @@ // Params: // - #k: The key type. // - #v: The value type.-@value interface KVWriter<#k,#v|> {+@value interface KVWriter<#k, #v|> {   // Sets or replaces the value associated with the key and returns self.-  set (#k,#v) -> (#self)+  set (#k, #v) -> (#self)   // Removes the value associated with the key if present and returns self.   remove (#k) -> (#self) }@@ -84,7 +84,7 @@ // - #v: The value type. @value interface KVExchange<#k|#v|> {   // Replaces the value if it does not exist and returns the final value.-  weakSet (#k,#v) -> (#v)+  weakSet (#k, #v) -> (#v)    // Swap the value associated with the key.   //@@ -94,7 +94,7 @@   //   // Returns:   // - optional #v: Previous value, or empty if none existed.-  swap (#k,optional #v) -> (optional #v)+  swap (#k, optional #v) -> (optional #v) }  // Writing to a set of values.@@ -118,13 +118,13 @@ }  // Factory for creating a new key-value pair.-@type interface KVFactory<#k,#v|> {+@type interface KVFactory<#k, #v|> {   // Create a new pair from the provided key and value.-  newNode (#k,#v) -> (#self)+  newNode (#k, #v) -> (#self) }  // A single key-value pair from a KVReader.-@value interface KeyValue<|#k,#v> {+@value interface KeyValue<|#k, #v> {   // Get the key.   //   // Notes:
lib/container/list.0rp view
@@ -38,7 +38,7 @@  // List element that supports reverse iteration. @value interface DoubleNode<|#n|#x> {-  refines ListNode<#n,#x>+  refines ListNode<#n, #x>    // Return the previous element.   prev () -> (optional #self)@@ -63,10 +63,10 @@   defines NewNode<#x>   // Duplication happens only in the forward direction.   refines Duplicate-  refines DoubleNode<LinkedNode<#x>,#x>+  refines DoubleNode<LinkedNode<#x>, #x>    // Create a new builder.-  @type builder () -> (ListBuilder<#x,#self>)+  @type builder () -> (ListBuilder<#x, #self>)    // Set the value held by the node.   @value set (#x) -> (#self)@@ -80,10 +80,10 @@ concrete ForwardNode<#x> {   defines NewNode<#x>   refines Duplicate-  refines ListNode<ForwardNode<#x>,#x>+  refines ListNode<ForwardNode<#x>, #x>    // Create a new builder.-  @type builder () -> (ListBuilder<#x,#self>)+  @type builder () -> (ListBuilder<#x, #self>)    // Set the value held by the node.   @value set (#x) -> (#self)@@ -93,7 +93,7 @@ concrete ListBuilder<#x|#n> {   refines Append<#x>   #n defines NewNode<#x>-  #n requires ListNode<#n,#x>+  #n requires ListNode<#n, #x>    // Create a new builder.   @type new () -> (#self)@@ -112,5 +112,5 @@   //   head/tail, but that tail will no longer be the end.   // - Calling mutating functions (e.g., setNext, setPrev) on any of the   //   elements between the returned head/tail will invalidate the builder.-  @value build () -> (optional #n,optional #n)+  @value build () -> (optional #n, optional #n) }
lib/container/sorted-map.0rp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -21,15 +21,16 @@ // Params: // - #k: The key type. // - #v: The value type.-concrete SortedMap<#k,#v> {+concrete SortedMap<#k, #v> {   defines Default   refines Container-  refines DefaultOrder<KeyValue<#k,#v>>+  refines DefaultOrder<KeyValue<#k, #v>>   refines Duplicate   refines KeyOrder<#k>-  refines KVExchange<#k,#v>-  refines KVWriter<#k,#v>-  refines KVReader<#k,#v>+  refines KVExchange<#k, #v>+  refines KVWriter<#k, #v>+  refines KVReader<#k, #v>+  refines SetReader<#k>   refines ValueOrder<#v>   #k immutable   #k defines LessThan<#k>@@ -44,7 +45,7 @@   // - Traversal of the entire map is amortized O(n); however, the cost of any   //   particular iteration could be up to O(log n).   // - The overall memory cost is O(log n).-  @value defaultOrder () -> (optional Order<KeyValue<#k,#v>>)+  @value defaultOrder () -> (optional Order<KeyValue<#k, #v>>)    // Traverse the map in the reverse order of defaultOrder().   //@@ -52,19 +53,19 @@   // - Traversal of the entire map is amortized O(n); however, the cost of any   //   particular iteration could be up to O(log n).   // - The overall memory cost is O(log n).-  @value reverseOrder () -> (optional Order<KeyValue<#k,#v>>)+  @value reverseOrder () -> (optional Order<KeyValue<#k, #v>>)    // Start forward traversal (same as defaultOrder()) from the specified key.   //   // Notes:   // - If the key does not exist in the SortedMap, the position right after   //   where it would be (in the forward direction) is returned.-  @value getForward (#k) -> (optional Order<KeyValue<#k,#v>>)+  @value getForward (#k) -> (optional Order<KeyValue<#k, #v>>)    // Start reverse traversal (same as reverseOrder()) from the specified key.   //   // Notes:   // - If the key does not exist in the SortedMap, the position right after   //   where it would be (in the reverse direction) is returned.-  @value getReverse (#k) -> (optional Order<KeyValue<#k,#v>>)+  @value getReverse (#k) -> (optional Order<KeyValue<#k, #v>>) }
lib/container/sorting.0rp view
@@ -28,7 +28,7 @@   // - Worst-case storage is O(1).   @category sort<#x>     #x defines LessThan<#x>-  ([ReadAt<#x>&WriteAt<#x>]) -> ()+  ([ReadAt<#x> & WriteAt<#x>]) -> ()    // In-place unstable sorting of a random-access container.   //@@ -43,17 +43,17 @@   // Example:   //   //   // Sort myIntContainer in reverse order. (Reversed is from lib/util.)-  //   \ Sorting:sortWith<?,Reversed<Int>>(myIntContainer)-  @category sortWith<#x,#xx>+  //   \ Sorting:sortWith<?, Reversed<Int>>(myIntContainer)+  @category sortWith<#x, #xx>     #xx defines LessThan<#x>-  ([ReadAt<#x>&WriteAt<#x>]) -> ()+  ([ReadAt<#x> & WriteAt<#x>]) -> ()    // The same as sortWith, but with LessThan2 instead of LessThan.   @category sortWith2<#x>-  ([ReadAt<#x>&WriteAt<#x>],LessThan2<#x>) -> ()+  ([ReadAt<#x> & WriteAt<#x>], LessThan2<#x>) -> ()    // In-place order reversal of a random-access container.-  @category reverse<#x> ([ReadAt<#x>&WriteAt<#x>]) -> ()+  @category reverse<#x> ([ReadAt<#x> & WriteAt<#x>]) -> ()    // In-place stable sorting of an iterable list.   //@@ -69,9 +69,9 @@   // - Worst-case storage is O(1).   // - If the node is not the actual head, the part of the list being sorted   //   might become detached from the earlier part of the list.-  @category sortList<#n,#x>+  @category sortList<#n, #x>     #x defines LessThan<#x>-    #n requires ListNode<#n,#x>+    #n requires ListNode<#n, #x>   (optional #n) -> (optional #n)    // In-place stable sorting of an iterable list.@@ -93,16 +93,16 @@   // Example:   //   //   // Sort myIntContainer in reverse order. (Reversed is from lib/util.)-  //   optional ListNode<#n,#x> newHead <- Sorting:sortListWith<?,?,Reversed<Int>>(oldHead)-  @category sortListWith<#n,#x,#xx>+  //   optional ListNode<#n, #x> newHead <- Sorting:sortListWith<?, ?, Reversed<Int>>(oldHead)+  @category sortListWith<#n, #x, #xx>     #xx defines LessThan<#x>-    #n requires ListNode<#n,#x>+    #n requires ListNode<#n, #x>   (optional #n) -> (optional #n)    // The same as sortListWith, but with LessThan2 instead of LessThan.-  @category sortListWith2<#n,#x>-    #n requires ListNode<#n,#x>-  (optional #n,LessThan2<#x>) -> (optional #n)+  @category sortListWith2<#n, #x>+    #n requires ListNode<#n, #x>+  (optional #n, LessThan2<#x>) -> (optional #n)    // Reverses the list in place and returns the new head.   //@@ -112,7 +112,7 @@   // Notes:   // - If the node is not the actual head, the part of the list being reversed   //   might become detached from the earlier part of the list.-  @category reverseList<#n,#x>-    #n requires ListNode<#n,#x>+  @category reverseList<#n, #x>+    #n requires ListNode<#n, #x>   (optional #n) -> (optional #n) }
lib/container/src/auto-tree.0rx view
@@ -41,11 +41,11 @@   }    get (k) {-    return find(root,k)+    return find(root, k)   } -  weakSet (k,v) {-    root, optional #v v2 <- insertWeak(root,k,v)+  weakSet (k, v) {+    root, optional #v v2 <- insertWeak(root, k, v)     if (`present` v2) {       return `require` v2     } else {@@ -54,8 +54,8 @@     }   } -  swap (k,v) (old) {-    root, old <- exchange(root,k,v)+  swap (k, v) (old) {+    root, old <- exchange(root, k, v)     if (!present(v) && present(old)) {       treeSize <- treeSize-1     } elif (present(v) && !present(old)) {@@ -63,22 +63,22 @@     }   } -  @type exchange (optional #n,#k,optional #v) -> (optional #n,optional #v)-  exchange (node,k,v) (newRoot,old) {+  @type exchange (optional #n, #k, optional #v) -> (optional #n, optional #v)+  exchange (node, k, v) (newRoot, old) {     if (!present(node)) {       if (present(v)) {-        return #n.newNode(k,require(v)), empty+        return #n.newNode(k, require(v)), empty       } else {         return empty, empty       }     }     #n node2 <- require(node)     if (k `#k.lessThan` node2.getKey()) {-      newRoot, old <- exchange(node2.getLower(),k,v)+      newRoot, old <- exchange(node2.getLower(), k, v)       \ node2.setLower(newRoot)       newRoot <- rebalance(node2)     } elif (node2.getKey() `#k.lessThan` k) {-      newRoot, old <- exchange(node2.getHigher(),k,v)+      newRoot, old <- exchange(node2.getHigher(), k, v)       \ node2.setHigher(newRoot)       newRoot <- rebalance(node2)     } elif (present(v)) {@@ -93,18 +93,18 @@   }  -  @type insertWeak (optional #n,#k,#v) -> (optional #n,optional #v)-  insertWeak (node,k,v) (newRoot,value) {+  @type insertWeak (optional #n, #k, #v) -> (optional #n, optional #v)+  insertWeak (node, k, v) (newRoot, value) {     if (!present(node)) {-      return #n.newNode(k,v), empty+      return #n.newNode(k, v), empty     }     #n node2 <- require(node)     if (k `#k.lessThan` node2.getKey()) {-      newRoot, value <- insertWeak(node2.getLower(),k,v)+      newRoot, value <- insertWeak(node2.getLower(), k, v)       \ node2.setLower(newRoot)       newRoot <- rebalance(node2)     } elif (node2.getKey() `#k.lessThan` k) {-      newRoot, value <- insertWeak(node2.getHigher(),k,v)+      newRoot, value <- insertWeak(node2.getHigher(), k, v)       \ node2.setHigher(newRoot)       newRoot <- rebalance(node2)     } else {@@ -112,15 +112,15 @@     }   } -  @type find (optional #n,#k) -> (optional #v)-  find (node,k) {+  @type find (optional #n, #k) -> (optional #v)+  find (node, k) {     if (present(node)) {       scoped {         #n node2 <- require(node)       } in if (k `#k.lessThan` node2.getKey()) {-        return find(node2.getLower(),k)+        return find(node2.getLower(), k)       } elif (node2.getKey() `#k.lessThan` k) {-        return find(node2.getHigher(),k)+        return find(node2.getHigher(), k)       } else {         return node2.getValue()       }@@ -195,13 +195,13 @@       \ node.setHigher(temp)     }     if (present(newNode)) {-      \ swapChildren(node,require(newNode))+      \ swapChildren(node, require(newNode))       \ require(newNode).updateNode()     }   } -  @type removeHighest (optional #n) -> (optional #n,optional #n)-  removeHighest (node) (newNode,removed) {+  @type removeHighest (optional #n) -> (optional #n, optional #n)+  removeHighest (node) (newNode, removed) {     if (!present(node)) {       return empty, empty     }@@ -217,8 +217,8 @@     }   } -  @type removeLowest (optional #n) -> (optional #n,optional #n)-  removeLowest (node) (newNode,removed) {+  @type removeLowest (optional #n) -> (optional #n, optional #n)+  removeLowest (node) (newNode, removed) {     if (!present(node)) {       return empty, empty     }@@ -234,8 +234,8 @@     }   } -  @type swapChildren (#n,#n) -> ()-  swapChildren (l,r) {+  @type swapChildren (#n, #n) -> ()+  swapChildren (l, r) {     scoped {       optional #n temp <- l.getLower()       \ l.setLower(r.getLower())@@ -250,30 +250,30 @@ define ForwardTreeOrder {   $ReadOnlyExcept[]$ -  @value BinaryTreeNode<#k,#v> node-  @value optional ForwardTreeOrder<#k,#v> prev+  @value BinaryTreeNode<#k, #v> node+  @value optional ForwardTreeOrder<#k, #v> prev    create (node) (current) {-    optional BinaryTreeNode<#k,#v> node2 <- node+    optional BinaryTreeNode<#k, #v> node2 <- node     current <- empty     while (present(node2)) {-      current <- ForwardTreeOrder<#k,#v>{ require(node2), current }+      current <- ForwardTreeOrder<#k, #v>{ require(node2), current }       node2 <- require(node2).getLower()     }   } -  seek (key,node) (current) {-    optional BinaryTreeNode<#k,#v> node2 <- node+  seek (key, node) (current) {+    optional BinaryTreeNode<#k, #v> node2 <- node     current <- empty     while (present(node2)) {       if (require(node2).getKey() `#k.lessThan` key) {         // Skip node2 in the traversal, since it's before key.         node2 <- require(node2).getHigher()       } elif (key `#k.lessThan` require(node2).getKey()) {-        current <- ForwardTreeOrder<#k,#v>{ require(node2), current }+        current <- ForwardTreeOrder<#k, #v>{ require(node2), current }         node2 <- require(node2).getLower()       } else {-        current <- ForwardTreeOrder<#k,#v>{ require(node2), current }+        current <- ForwardTreeOrder<#k, #v>{ require(node2), current }         break       }     }@@ -283,46 +283,46 @@     // Algorithm:     // 1. Pop self from the stack.     // 2. Traverse lower to the bottom starting from the higher child of self.-    optional BinaryTreeNode<#k,#v> node2 <- node.getHigher()+    optional BinaryTreeNode<#k, #v> node2 <- node.getHigher()     current <- prev     while (present(node2)) {-      current <- ForwardTreeOrder<#k,#v>{ require(node2), current }+      current <- ForwardTreeOrder<#k, #v>{ require(node2), current }       node2 <- require(node2).getLower()     }   }    get () {-    return SimpleKeyValue:new(node.getKey(),node.getValue())+    return SimpleKeyValue:new(node.getKey(), node.getValue())   } }  define ReverseTreeOrder {   $ReadOnlyExcept[]$ -  @value BinaryTreeNode<#k,#v> node-  @value optional ReverseTreeOrder<#k,#v> prev+  @value BinaryTreeNode<#k, #v> node+  @value optional ReverseTreeOrder<#k, #v> prev    create (node) (current) {-    optional BinaryTreeNode<#k,#v> node2 <- node+    optional BinaryTreeNode<#k, #v> node2 <- node     current <- empty     while (present(node2)) {-      current <- ReverseTreeOrder<#k,#v>{ require(node2), current }+      current <- ReverseTreeOrder<#k, #v>{ require(node2), current }       node2 <- require(node2).getHigher()     }   } -  seek (key,node) (current) {-    optional BinaryTreeNode<#k,#v> node2 <- node+  seek (key, node) (current) {+    optional BinaryTreeNode<#k, #v> node2 <- node     current <- empty     while (present(node2)) {       if (require(node2).getKey() `#k.lessThan` key) {-        current <- ReverseTreeOrder<#k,#v>{ require(node2), current }+        current <- ReverseTreeOrder<#k, #v>{ require(node2), current }         node2 <- require(node2).getHigher()       } elif (key `#k.lessThan` require(node2).getKey()) {         // Skip node2 in the traversal, since it's after key.         node2 <- require(node2).getLower()       } else {-        current <- ReverseTreeOrder<#k,#v>{ require(node2), current }+        current <- ReverseTreeOrder<#k, #v>{ require(node2), current }         break       }     }@@ -332,15 +332,15 @@     // Algorithm:     // 1. Pop self from the stack.     // 2. Traverse higher to the bottom starting from the lower child of self.-    optional BinaryTreeNode<#k,#v> node2 <- node.getLower()+    optional BinaryTreeNode<#k, #v> node2 <- node.getLower()     current <- prev     while (present(node2)) {-      current <- ReverseTreeOrder<#k,#v>{ require(node2), current }+      current <- ReverseTreeOrder<#k, #v>{ require(node2), current }       node2 <- require(node2).getHigher()     }   }    get () {-    return SimpleKeyValue:new(node.getKey(),node.getValue())+    return SimpleKeyValue:new(node.getKey(), node.getValue())   } }
lib/container/src/hashed-map.0rx view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -18,10 +18,10 @@  define HashedMap {   @value Int itemCount-  @value [DefaultOrder<HashRoot<#k,#v>>&ReadAt<HashRoot<#k,#v>>] table+  @value [DefaultOrder<HashRoot<#k, #v>> & ReadAt<HashRoot<#k, #v>>] table    new () {-    return #self{ 0, Vector:createSize<HashRoot<#k,#v>>($ExprLookup[HASH_TABLE_MIN_SIZE]$) }+    return #self{ 0, Vector:createSize<HashRoot<#k, #v>>($ExprLookup[HASH_TABLE_MIN_SIZE]$) }   }    default () {@@ -29,29 +29,33 @@   }    duplicate () {-    return #self{ itemCount, table.defaultOrder() `OrderH:duplicateTo` Vector<HashRoot<#k,#v>>.new() }+    return #self{ itemCount, table.defaultOrder() `OrderH:duplicateTo` Vector<HashRoot<#k, #v>>.new() }   }    size () {     return itemCount   } +  member (k) {+    return `present` delegate -> `get`+  }+   get (k) {     return table.readAt(getBin(k.hashed())).find(k)   } -  set (k,v) {-    \ swap(k,v)+  set (k, v) {+    \ swap(k, v)     return self   }    remove (k) {-    \ swap(k,empty)+    \ swap(k, empty)     return self   } -  weakSet (k,v) {-    optional #v value <- table.readAt(getBin(k.hashed())).weakReplace(k,v)+  weakSet (k, v) {+    optional #v value <- table.readAt(getBin(k.hashed())).weakReplace(k, v)     if (`present` value) {       return `require` value     } else {@@ -61,8 +65,8 @@     }   } -  swap (k,v) (old) {-    old <- table.readAt(getBin(k.hashed())).exchange(k,v)+  swap (k, v) (old) {+    old <- table.readAt(getBin(k.hashed())).exchange(k, v)     if (!present(v) && present(old)) {       itemCount <- itemCount-1       \ maybeResize()@@ -73,7 +77,7 @@   }    defaultOrder () {-    return HashedMapOrder<#k,#v>.new(itemCount,table)+    return HashedMapOrder<#k, #v>.new(itemCount, table)   }    keyOrder () {@@ -95,34 +99,34 @@    @value maybeResize () -> ()   maybeResize () {-    optional [DefaultOrder<HashRoot<#k,#v>>&ReadAt<HashRoot<#k,#v>>] newTable <- empty+    optional [DefaultOrder<HashRoot<#k, #v>> & ReadAt<HashRoot<#k, #v>>] newTable <- empty     if (itemCount >= $ExprLookup[HASH_TABLE_EXPAND_RATIO]$*table.size()) {-      newTable <- Vector:createSize<HashRoot<#k,#v>>(2*table.size())+      newTable <- Vector:createSize<HashRoot<#k, #v>>(2*table.size())     } elif ($ExprLookup[HASH_TABLE_CONTRACT_RATIO]$*itemCount < table.size() && table.size() > $ExprLookup[HASH_TABLE_MIN_SIZE]$) {-      newTable <- Vector:createSize<HashRoot<#k,#v>>(table.size()/2)+      newTable <- Vector:createSize<HashRoot<#k, #v>>(table.size()/2)     }     if (`present` newTable) {-      [DefaultOrder<HashRoot<#k,#v>>&ReadAt<HashRoot<#k,#v>>] oldTable <- table+      [DefaultOrder<HashRoot<#k, #v>> & ReadAt<HashRoot<#k, #v>>] oldTable <- table       table <- `require` newTable       $Hidden[newTable]$-      traverse (oldTable.defaultOrder() -> HashRoot<#k,#v> root) {-        traverse (root.defaultOrder() -> HashNode<#k,#v> node) {-          \ table.readAt(getBin(node.getKey().hashed())).exchange(node.getKey(),node.getValue())+      traverse (oldTable.defaultOrder() -> HashRoot<#k, #v> root) {+        traverse (root.defaultOrder() -> HashNode<#k, #v> node) {+          \ table.readAt(getBin(node.getKey().hashed())).exchange(node.getKey(), node.getValue())         }       }     }   } } -concrete HashNode<#k,#v> {+concrete HashNode<#k, #v> {   refines Duplicate   refines Order<#self> -  @type new (#k,#v,optional HashNode<#k,#v>) -> (#self)+  @type new (#k, #v, optional HashNode<#k, #v>) -> (#self)   @value getKey () -> (#k)   @value getValue () -> (#v)   @value setValue (#v) -> ()-  @value setNext (optional HashNode<#k,#v>) -> (optional #self)+  @value setNext (optional HashNode<#k, #v>) -> (optional #self) }  define HashNode {@@ -130,14 +134,14 @@    @value #k key   @value #v value-  @value optional HashNode<#k,#v> next+  @value optional HashNode<#k, #v> next -  new (key,value,next) {-    return #self{ key, value, next }+  new (key, value, next) {+    return delegate -> #self   }    duplicate () {-    optional HashNode<#k,#v> next2 <- empty+    optional HashNode<#k, #v> next2 <- empty     if (`present` next) {       next2 <- require(next).duplicate()     }@@ -156,21 +160,21 @@   } } -concrete HashRoot<#k,#v> {+concrete HashRoot<#k, #v> {   defines Default-  refines DefaultOrder<HashNode<#k,#v>>+  refines DefaultOrder<HashNode<#k, #v>>   refines Duplicate   #k defines Equals<#k> -  @value exchange (#k,optional #v) -> (optional #v)-  @value weakReplace (#k,#v) -> (optional #v)+  @value exchange (#k, optional #v) -> (optional #v)+  @value weakReplace (#k, #v) -> (optional #v)   @value find (#k) -> (optional #v)   // Override to allow returning HashNode directly.-  @value defaultOrder () -> (optional HashNode<#k,#v>)+  @value defaultOrder () -> (optional HashNode<#k, #v>) }  define HashRoot {-  @value optional HashNode<#k,#v> root+  @value optional HashNode<#k, #v> root    default () {     return #self{ empty }@@ -188,17 +192,17 @@     }   } -  exchange (k,v) (old) {+  exchange (k, v) (old) {     old <- empty     scoped {-      optional HashNode<#k,#v> prev <- empty-    } in traverse (root -> HashNode<#k,#v> node) {+      optional HashNode<#k, #v> prev <- empty+    } in traverse (root -> HashNode<#k, #v> node) {       if (node.getKey() `#k.equals` k) {         old <- node.getValue()         if (`present` v) {           \ node.setValue(`require` v)         } else {-          optional HashNode<#k,#v> next <- node.setNext(empty)+          optional HashNode<#k, #v> next <- node.setNext(empty)           if (`present` prev) {             \ require(prev).setNext(next)           } else {@@ -211,23 +215,23 @@       prev <- node     }     if (`present` v) {-      root <- HashNode<#k,#v>.new(k,`require` v,root)+      root <- HashNode<#k, #v>.new(k, `require` v, root)     }   } -  weakReplace (k,v) {-    traverse (root -> HashNode<#k,#v> node) {+  weakReplace (k, v) {+    traverse (root -> HashNode<#k, #v> node) {       if (node.getKey() `#k.equals` k) {         return node.getValue()       }     }-    root <- HashNode<#k,#v>.new(k,v,root)+    root <- HashNode<#k, #v>.new(k, v, root)     return empty   }    find (k) (v) {     v <- empty-    traverse (root -> HashNode<#k,#v> node) {+    traverse (root -> HashNode<#k, #v> node) {       if (node.getKey() `#k.equals` k) {         return node.getValue()       }@@ -235,22 +239,22 @@   } } -concrete HashedMapOrder<#k,#v> {-  refines Order<KeyValue<#k,#v>>+concrete HashedMapOrder<#k, #v> {+  refines Order<KeyValue<#k, #v>> -  @type new (Int,DefaultOrder<HashRoot<#k,#v>>) -> (optional #self)+  @type new (Int, DefaultOrder<HashRoot<#k, #v>>) -> (optional #self) }  define HashedMapOrder {   @value Int count-  @value optional Order<HashRoot<#k,#v>> root-  @value HashNode<#k,#v> node+  @value optional Order<HashRoot<#k, #v>> root+  @value HashNode<#k, #v> node -  new (count,table) (next) {+  new (count, table) (next) {     next <- empty     if (count > 0) {       scoped {-        optional Order<HashRoot<#k,#v>> root, optional HashNode<#k,#v> node <- seekNext(table.defaultOrder())+        optional Order<HashRoot<#k, #v>> root, optional HashNode<#k, #v> node <- seekNext(table.defaultOrder())       } in if (`present` node) {         next <- #self{ count, root, `require` node }       }@@ -258,20 +262,20 @@   }    get () {-    return SimpleKeyValue:new(node.getKey(),node.getValue())+    return SimpleKeyValue:new(node.getKey(), node.getValue())   }    next () (next) {     next <- empty     if ((count <- count-1) > 0) {       scoped {-        optional HashNode<#k,#v> newNode <- node.next()+        optional HashNode<#k, #v> newNode <- node.next()       } in if (`present` newNode) {         node <- `require` newNode         return self       }       scoped {-        root, optional HashNode<#k,#v> newNode <- seekNext(root)+        root, optional HashNode<#k, #v> newNode <- seekNext(root)       } in if (`present` newNode) {         node <- `require` newNode         return self@@ -279,8 +283,8 @@     }   } -  @type seekNext (optional Order<HashRoot<#k,#v>>) -> (optional Order<HashRoot<#k,#v>>,optional HashNode<#k,#v>)-  seekNext (start) (root,node) {+  @type seekNext (optional Order<HashRoot<#k, #v>>) -> (optional Order<HashRoot<#k, #v>>, optional HashNode<#k, #v>)+  seekNext (start) (root, node) {     root <- start     node <- empty     $Hidden[start]$
lib/container/src/hashed-set.0rx view
@@ -17,14 +17,14 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define HashedSet {-  @value HashedMap<#k,any> map+  @value HashedMap<#k, any> map    default () {     return new()   }    new () {-    return #self{ HashedMap<#k,any>.new() }+    return #self{ HashedMap<#k, any>.new() }   }    size () {@@ -36,7 +36,7 @@   }    add (k) {-    \ map.set(k,Void.default())+    \ map.set(k, Void.default())     return self   } 
lib/container/src/helpers.0rx view
@@ -17,11 +17,11 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define KeyValueH {-  lessThan (x,y) {-    return lessThanWith<#k,#v,#k,#v>(x,y)+  lessThan (x, y) {+    return lessThanWith<#k, #v, #k, #v>(x, y)   } -  lessThanWith (x,y) {+  lessThanWith (x, y) {     if (x.getKey() `#kk.lessThan` y.getKey()) {       return true     } elif (y.getKey() `#kk.lessThan` x.getKey()) {@@ -31,11 +31,11 @@     }   } -  equals (x,y) {-    return equalsWith<#k,#v,#k,#v>(x,y)+  equals (x, y) {+    return equalsWith<#k, #v, #k, #v>(x, y)   } -  equalsWith (x,y) {+  equalsWith (x, y) {     if (!(x.getKey() `#kk.equals` y.getKey())) {       return false     } else {
lib/container/src/list.0rx view
@@ -35,7 +35,7 @@   }    builder () {-    return ListBuilder<#x,#self>.new()+    return ListBuilder<#x, #self>.new()   }    next () {@@ -47,7 +47,7 @@   }    duplicate () {-    $Hidden[prev,next,value]$+    $Hidden[prev, next, value]$     return require(builder().appendAll(self).build(){0})   } @@ -104,7 +104,7 @@   }    builder () {-    return ListBuilder<#x,#self>.new()+    return ListBuilder<#x, #self>.new()   }    next () {@@ -112,7 +112,7 @@   }    duplicate () {-    $Hidden[next,value]$+    $Hidden[next, value]$     return require(builder().appendAll(self).build(){0})   } 
lib/container/src/queue.0rx view
@@ -30,7 +30,7 @@   }    duplicate () {-    $ReadOnly[size,head]$+    $ReadOnly[size, head]$     $Hidden[tail]$     scoped {       optional ForwardNode<#x> head2, optional ForwardNode<#x> tail2 <-
lib/container/src/sorted-map.0rx view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -17,20 +17,24 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define SortedMap {-  @value AutoBinaryTree<SortedMapNode<#k,#v>,#k,#v,BinaryTreeNode<#k,#v>> map+  @value AutoBinaryTree<SortedMapNode<#k, #v>, #k, #v, BinaryTreeNode<#k, #v>> map    default () {     return new()   }    new () {-    return #self{ AutoBinaryTree<SortedMapNode<#k,#v>,#k,#v,BinaryTreeNode<#k,#v>>.new() }+    return #self{ AutoBinaryTree<SortedMapNode<#k, #v>, #k, #v, BinaryTreeNode<#k, #v>>.new() }   }    size () {     return map.size()   } +  member (k) {+    return `present` delegate -> `get`+  }+   duplicate () {     return #self{ map.duplicate() }   }@@ -39,22 +43,22 @@     return map.get(k)   } -  set (k,v) {-    \ swap(k,v)+  set (k, v) {+    \ swap(k, v)     return self   }    remove (k) {-    \ swap(k,empty)+    \ swap(k, empty)     return self   } -  weakSet (k,v) {-    return map.weakSet(k,v)+  weakSet (k, v) {+    return map.weakSet(k, v)   } -  swap (k,v) {-    return map.swap(k,v)+  swap (k, v) {+    return map.swap(k, v)   }    defaultOrder () {@@ -66,11 +70,11 @@   }    getForward (k) {-    return ForwardTreeOrder:seek(k,map.getRoot())+    return ForwardTreeOrder:seek(k, map.getRoot())   }    getReverse (k) {-    return ReverseTreeOrder:seek(k,map.getRoot())+    return ReverseTreeOrder:seek(k, map.getRoot())   }    keyOrder () {@@ -83,24 +87,24 @@ }  define ValidatedTree {-  @value AutoBinaryTree<SortedMapNode<#k,#v>,#k,#v,BinaryTreeNode<#k,#v>> map+  @value AutoBinaryTree<SortedMapNode<#k, #v>, #k, #v, BinaryTreeNode<#k, #v>> map    new () { $NoTrace$-    return #self{ AutoBinaryTree<SortedMapNode<#k,#v>,#k,#v,BinaryTreeNode<#k,#v>>.new() }+    return #self{ AutoBinaryTree<SortedMapNode<#k, #v>, #k, #v, BinaryTreeNode<#k, #v>>.new() }   }    size () { $NoTrace$     return map.size()   } -  set (k,v) { $NoTrace$-    \ map.swap(k,v)+  set (k, v) { $NoTrace$+    \ map.swap(k, v)     \ validate(map.getRoot())     return self   }    remove (k) { $NoTrace$-    \ map.swap(k,empty)+    \ map.swap(k, empty)     \ validate(map.getRoot())     return self   }@@ -109,7 +113,7 @@     return map.get(k)   } -  @type validate (optional BinaryTreeNode<#k,#v>) -> ()+  @type validate (optional BinaryTreeNode<#k, #v>) -> ()   validate (node) { $NoTrace$     if (present(node)) {       \ validateOrder(require(node))@@ -117,7 +121,7 @@     }   } -  @type validateOrder (BinaryTreeNode<#k,#v>) -> ()+  @type validateOrder (BinaryTreeNode<#k, #v>) -> ()   validateOrder (node) { $NoTrace$     if (present(node.getLower())) {       if (!(require(node.getLower()).getKey() `#k.lessThan` node.getKey())) {@@ -133,7 +137,7 @@     }   } -  @type validateBalance (BinaryTreeNode<#k,#v>) -> ()+  @type validateBalance (BinaryTreeNode<#k, #v>) -> ()   validateBalance (node) { $NoTrace$     scoped {       Int balance <- 0@@ -156,9 +160,9 @@   } } -concrete SortedMapNode<#k,#v> {-  defines KVFactory<#k,#v>-  refines BalancedTreeNode<SortedMapNode<#k,#v>,#k,#v>+concrete SortedMapNode<#k, #v> {+  defines KVFactory<#k, #v>+  refines BalancedTreeNode<SortedMapNode<#k, #v>, #k, #v>   refines Duplicate } @@ -171,7 +175,7 @@   @value optional #self lower   @value optional #self higher -  newNode (k,v) {+  newNode (k, v) {     return #self{ 1, k, v, empty, empty }   } 
lib/container/src/sorted-set.0rx view
@@ -17,14 +17,14 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define SortedSet {-  @value SortedMap<#k,any> map+  @value SortedMap<#k, any> map    default () {     return new()   }    new () {-    return #self{ SortedMap<#k,any>.new() }+    return #self{ SortedMap<#k, any>.new() }   }    size () {@@ -36,7 +36,7 @@   }    add (k) {-    \ map.set(k,Void.default())+    \ map.set(k, Void.default())     return self   } 
lib/container/src/sorting.0rx view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -18,15 +18,15 @@  define Sorting {   sort (seq) {-    \ sortWith<#x,#x>(seq)+    \ sortWith<#x, #x>(seq)   }    sortWith (seq) {-    \ seq `sortWith2` AsLessThan2<#x,#xx>.new()+    \ seq `sortWith2` AsLessThan2<#x, #xx>.new()   } -  sortWith2 (seq,compare) {-    \ HeapSort<#x>.inPlace(seq,compare)+  sortWith2 (seq, compare) {+    \ HeapSort<#x>.inPlace(seq, compare)   }    reverse (seq) {@@ -36,23 +36,23 @@       $ReadOnly[i]$       Int j <- seq.size()-i-1       #x temp <- seq.readAt(i)-      \ seq.writeAt(i,seq.readAt(j))-      \ seq.writeAt(j,temp)+      \ seq.writeAt(i, seq.readAt(j))+      \ seq.writeAt(j, temp)     } update {       i <- i-1     }   }    sortList (head) {-    return sortListWith<#n,#x,#x>(head)+    return sortListWith<#n, #x, #x>(head)   }    sortListWith (head) {-    return head `sortListWith2` AsLessThan2<#x,#xx>.new()+    return head `sortListWith2` AsLessThan2<#x, #xx>.new()   } -  sortListWith2 (head,compare) {-    return MergeSort<#n,#x>.sort(head,compare)+  sortListWith2 (head, compare) {+    return MergeSort<#n, #x>.sort(head, compare)   }    reverseList (head) (head2) {@@ -80,17 +80,17 @@ // Putting the params at the top level allows helpers to be called without // needing to pass the params every time. concrete HeapSort<#x> {-  @type inPlace ([ReadAt<#x>&WriteAt<#x>],LessThan2<#x>) -> ()+  @type inPlace ([ReadAt<#x> & WriteAt<#x>], LessThan2<#x>) -> () }  define HeapSort {   $ReadOnlyExcept[]$ -  @value [ReadAt<#x>&WriteAt<#x>] seq+  @value [ReadAt<#x> & WriteAt<#x>] seq   @value LessThan2<#x> compare -  inPlace (seq,compare) {-    \ #self{ seq, compare }.execute()+  inPlace (seq, compare) {+    \ (delegate -> #self).execute()   }    @value execute () -> ()@@ -100,7 +100,7 @@       Int i <- seq.size()/2-1     } in while (i >= 0) {       $ReadOnly[i]$-      \ sift(i,seq.size())+      \ sift(i, seq.size())     } update {       i <- i-1     }@@ -110,15 +110,15 @@       Int i <- seq.size()-1     } in while (i >= 0) {       $ReadOnly[i]$-      \ swap(0,i)-      \ sift(0,i)+      \ swap(0, i)+      \ sift(0, i)     } update {       i <- i-1     }   } -  @value sift (Int,Int) -> ()-  sift (start,size) { $NoTrace$+  @value sift (Int, Int) -> ()+  sift (start, size) { $NoTrace$     scoped {       Int last         <- start       Int indexLargest <- last@@ -127,7 +127,7 @@       $ReadOnly[last]$       Int left  <- 2*last+1       Int right <- 2*last+2-      $ReadOnly[left,right]$+      $ReadOnly[left, right]$       if (seq.readAt(indexLargest) `compare.lessThan2` seq.readAt(left)) {         indexLargest <- left       }@@ -138,33 +138,33 @@         break       }     } update {-      \ swap(last,indexLargest)+      \ swap(last, indexLargest)       last <- indexLargest     }   } -  @value swap (Int,Int) -> ()-  swap (i,j) { $NoTrace$+  @value swap (Int, Int) -> ()+  swap (i, j) { $NoTrace$     if (i != j) {       #x temp <- seq.readAt(i)-      \ seq.writeAt(i,seq.readAt(j))-      \ seq.writeAt(j,temp)+      \ seq.writeAt(i, seq.readAt(j))+      \ seq.writeAt(j, temp)     }   } }  // Putting the params at the top level allows helpers to be called without // needing to pass the params every time.-concrete MergeSort<#n,#x> {-  #n requires ListNode<#n,#x>+concrete MergeSort<#n, #x> {+  #n requires ListNode<#n, #x> -  @type sort (optional #n,LessThan2<#x>) -> (optional #n)+  @type sort (optional #n, LessThan2<#x>) -> (optional #n) }  define MergeSort {   @value LessThan2<#x> compare -  sort (head,compare) {+  sort (head, compare) {     return #self{ compare }.iterated(head)   } @@ -188,7 +188,7 @@         optional #n right <- left  `splitAt` chunk         next              <- right `splitAt` chunk         $Hidden[next]$-        $ReadOnly[left,right]$+        $ReadOnly[left, right]$         dirty <- dirty || present(right)         optional #n newHead, optional #n newTail <- left `merge` right         if (!present(head2)) {@@ -203,8 +203,8 @@     }   } -  @value splitAt (optional #n,Int) -> (optional #n)-  splitAt (head,n) {+  @value splitAt (optional #n, Int) -> (optional #n)+  splitAt (head, n) {     optional #n head2 <- head     $Hidden[head]$ @@ -223,14 +223,14 @@     return empty   } -  @value merge (optional #n,optional #n) -> (optional #n,optional #n)-  merge (left,right) (head,tail) {+  @value merge (optional #n, optional #n) -> (optional #n, optional #n)+  merge (left, right) (head, tail) {     head <- empty     tail <- empty      optional #n left2  <- left     optional #n right2 <- right-    $Hidden[left,right]$+    $Hidden[left, right]$      while (present(left2) && present(right2)) {       #n append <- defer
+ lib/container/src/testing.0rx view
@@ -0,0 +1,233 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++define CheckSet {+  equals (expected) {+    return SetEquals<#k>.new(expected)+  }+}++define CheckMap {+  using (expected) {+    return MapAdapter<#k, #v>.new(expected)+  }++  equals (expected) {+    return MapEquals<#k, #v>.new(expected)+  }++  matches (expected) {+    return MapMatches<#k, #v>.new(expected)+  }+}++concrete MapAdapter<#k, #v> {+  #v requires TestCompare<#v>++  @type new ([SetReader<#k> & DefaultOrder<KeyValue<#k, #v>>]) -> ([SetReader<#k> & DefaultOrder<KeyValue<#k, ValueMatcher<#v>>>])+}++define MapAdapter {+  $ReadOnlyExcept[current]$++  refines SetReader<#k>+  refines DefaultOrder<KeyValue<#k, ValueMatcher<#v>>>+  refines Order<KeyValue<#k, ValueMatcher<#v>>>++  @value [SetReader<#k> & DefaultOrder<KeyValue<#k, #v>>] original+  @value optional Order<KeyValue<#k, #v>> current++  new (original) {+    return #self{ original, empty }+  }++  defaultOrder () {+    return #self{ original, original.defaultOrder() }+  }++  get () {+    scoped {+      KeyValue<#k, #v> keyValue <- `require` current&.get()+    } in return SimpleKeyValue:new(keyValue.getKey(), CheckValue:using(keyValue.getValue()))+  }++  next () {+    if (`present` (current <- current&.next())) {+      return self+    } else {+      return empty+    }+  }++  member (k) {+    return delegate -> `original.member`+  }+}++concrete SetEquals<#k> {+  #k requires Formatted++  @type new ([SetReader<#k> & DefaultOrder<#k>]) -> (ValueMatcher<[SetReader<#k> & DefaultOrder<#k>]>)+}++define SetEquals {+  $ReadOnlyExcept[]$++  refines ValueMatcher<[SetReader<#k> & DefaultOrder<#k>]>++  @value [SetReader<#k> & DefaultOrder<#k>] expected++  new (expected) {+    return delegate -> #self+  }++  check (actual, report) {+    traverse (expected.defaultOrder() -> #k currentExpected) {+      if (`present` actual && ! `require(actual).member` currentExpected) {+        \ report.addError(message: String.builder()+            .append("\"")+            .append(currentExpected)+            .append("\" is missing")+            .build())+      }+    }+    traverse (actual&.defaultOrder() -> #k currentActual) {+      if (! `expected.member` currentActual) {+        \ report.addError(message: String.builder()+            .append("\"")+            .append(currentActual)+            .append("\" is unexpected")+            .build())+      }+    }+  }++  summary () {+    return "set equals"+  }+}++concrete MapEquals<#k, #v> {+  #k requires Formatted+  #v requires Formatted+  #v defines Equals<#v>++  @type new ([SetReader<#k> & DefaultOrder<KeyValue<#k, #v>>]) -> (ValueMatcher<[KVReader<#k, #v> & KeyOrder<#k>]>)+}++define MapEquals {+  $ReadOnlyExcept[]$++  refines ValueMatcher<[KVReader<#k, #v> & KeyOrder<#k>]>++  @value [SetReader<#k> & DefaultOrder<KeyValue<#k, #v>>] expected++  new (expected) {+    return delegate -> #self+  }++  check (actual, report) {+    traverse (expected.defaultOrder() -> KeyValue<#k, #v> current) {+      optional #v value <- actual&.get(current.getKey())+      $Hidden[actual, expected]$+      if (! `present` value) {+        \ report.addError(message: String.builder()+            .append("Key ")+            .append(`Format:autoFormat` current.getKey())+            .append(" is missing")+            .build())+      } elif (!(require(value) `#v.equals` current.getValue())) {+        TestReport newReport <- report.newSection(title: String.builder()+            .append("Key ")+            .append(`Format:autoFormat` current.getKey())+            .build())+        $Hidden[report]$+        \ newReport.addError(message: String.builder()+            .append(`Format:autoFormat` value)+            .append(" does not equal ")+            .append(`Format:autoFormat` current.getValue())+            .build())+      }+    }+    traverse (actual&.keyOrder() -> #k current) {+      if (! `expected.member` current) {+        \ report.addError(message: String.builder()+            .append("Key ")+            .append(`Format:autoFormat` current)+            .append(" is unexpected")+            .build())+      }+    }+  }++  summary () {+    return "map equals"+  }+}++concrete MapMatches<#k, #v> {+  #k requires Formatted++  @type new ([SetReader<#k> & DefaultOrder<KeyValue<#k, ValueMatcher<#v>>>]) -> (ValueMatcher<[KVReader<#k, #v> & KeyOrder<#k>]>)+}++define MapMatches {+  $ReadOnlyExcept[]$++  refines ValueMatcher<[KVReader<#k, #v> & KeyOrder<#k>]>++  @value [SetReader<#k> & DefaultOrder<KeyValue<#k, ValueMatcher<#v>>>] expected++  new (expected) {+    return delegate -> #self+  }++  check (actual, report) {+    traverse (expected.defaultOrder() -> KeyValue<#k, ValueMatcher<#v>> current) {+      optional #v value <- actual&.get(current.getKey())+      $Hidden[actual, expected]$+      if (! `present` value) {+        \ report.addError(message: String.builder()+            .append("Key ")+            .append(`Format:autoFormat` current.getKey())+            .append(" is missing")+            .build())+      } else {+        TestReport newReport <- report.newSection(title: String.builder()+            .append("Key ")+            .append(`Format:autoFormat` current.getKey())+            .build())+        $Hidden[report]$+        \ require(value) `current.getValue().check` newReport+      }+    }+    traverse (actual&.keyOrder() -> #k current) {+      if (! `expected.member` current) {+        \ report.addError(message: String.builder()+            .append("Key ")+            .append(`Format:autoFormat` current)+            .append(" is unexpected")+            .build())+      }+    }+  }++  summary () {+    return "map matches"+  }+}
lib/container/src/type-map.0rx view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -17,22 +17,22 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define TypeMap {-  @value SortedMap<TypeKey<any>,GenericValue<any>> map+  @value SortedMap<TypeKey<any>, GenericValue<any>> map    default () {     return new()   }    new () {-    return TypeMap{ SortedMap<TypeKey<any>,GenericValue<any>>.new() }+    return TypeMap{ SortedMap<TypeKey<any>, GenericValue<any>>.new() }   }    duplicate () {     return #self{ map.duplicate() }   } -  set (k,v) {-    \ map.set(k,GenericValue:create(v))+  set (k, v) {+    \ map.set(k, GenericValue:create(v))     return self   } @@ -52,7 +52,7 @@   }    getAll (output) {-    traverse (map.defaultOrder() -> KeyValue<any,GenericValue<any>> pair) {+    traverse (map.defaultOrder() -> KeyValue<any, GenericValue<any>> pair) {       scoped {         optional #x value <- pair.getValue().check<#x>()       } in if (present(value)) {@@ -64,44 +64,29 @@ }  define TypeKey {-  $ReadOnlyExcept[counter]$--  @category Mutex counterMutex <- SpinlockMutex.new()-  @category Int   counter      <- 0-  @value Int index-   new () {-    scoped {-      \ counterMutex.lock()-    } cleanup {-      \ counterMutex.unlock()-    } in return TypeKey<#x>{ (counter <- counter+1) }+    return #self{ }   }    formatted () {     return String.builder()         .append(typename<#self>())         .append("{")-        .append(index)+        .append( `identify` self)         .append("}")         .build()   }    hashed () {-    return index.hashed()-  }--  lessThan (l,r) {-    return l.get() < r.get()+    return identify(self).hashed()   } -  equals (l,r) {-    return l.get() == r.get()+  lessThan (l, r) {+    return identify(l) < identify(r)   } -  @value get () -> (Int)-  get () {-    return index+  equals (l, r) {+    return identify(l) == identify(r)   } } @@ -116,10 +101,10 @@   @value #x value    create (v) {-    return GenericValue<#x>{ v }+    return delegate -> GenericValue<#x>   }    check () {-    return reduce<#x,#y>(value)+    return reduce<#x, #y>(value)   } }
+ lib/container/src/util.0rp view
@@ -0,0 +1,32 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++$ModuleOnly$++concrete Format {+  @category autoFormat<#x>+    #x requires Formatted+  (optional #x) -> (Formatted)+}++concrete TestValue {+  immutable+  refines TestCompare<TestValue>++  @type new (String) -> (TestValue)+}
+ lib/container/src/util.0rx view
@@ -0,0 +1,54 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++define Format {+  autoFormat (value) {+    if (`present` value) {+      return String.builder()+          .append("\"")+          .append(`require` value)+          .append("\"")+          .build()+    } else {+      return "empty"+    }+  }+}++define TestValue {+  @value String message++  new (message) {+    return delegate -> #self+  }++  testCompare (actual, report) {+    if (actual.message() != message) {+      \ report.addError(message: String.builder()+          .append(`Format:autoFormat` actual.message())+          .append(" does not equal ")+          .append(`Format:autoFormat` message)+          .build())+    }+  }++  @value message () -> (String)+  message () {+    return message+  }+}
lib/container/src/validated-tree.0rp view
@@ -26,8 +26,8 @@ //   therefore only be used in tests. concrete ValidatedTree<#k|#v|> {   refines Container-  refines KVWriter<#k,#v>-  refines KVReader<#k,#v>+  refines KVWriter<#k, #v>+  refines KVReader<#k, #v>   #k immutable   #k defines LessThan<#k> 
lib/container/src/wrappers.0rp view
@@ -18,14 +18,14 @@  $ModuleOnly$ -concrete SimpleKeyValue<|#k,#v> {-  @category new<#k,#v> (#k,#v) -> (KeyValue<#k,#v>)+concrete SimpleKeyValue<|#k, #v> {+  @category new<#k, #v> (#k, #v) -> (KeyValue<#k, #v>) }  concrete MapKeyOrder<#k> {-  @category new<#k> (optional Order<KeyValue<#k,any>>) -> (optional Order<#k>)+  @category new<#k> (optional Order<KeyValue<#k, any>>) -> (optional Order<#k>) }  concrete MapValueOrder<#v> {-  @category new<#v> (optional Order<KeyValue<any,#v>>) -> (optional Order<#v>)+  @category new<#v> (optional Order<KeyValue<any, #v>>) -> (optional Order<#v>) }
lib/container/src/wrappers.0rx view
@@ -19,13 +19,13 @@ define SimpleKeyValue {   $ReadOnlyExcept[]$ -  refines KeyValue<#k,#v>+  refines KeyValue<#k, #v>    @value #k key   @value #v value -  new (key,value) {-    return SimpleKeyValue<#k,#v>{ key, value }+  new (key, value) {+    return delegate -> SimpleKeyValue<#k, #v>   }    getKey () {@@ -40,7 +40,7 @@ define MapKeyOrder {   refines Order<#k> -  @value Order<KeyValue<#k,any>> order+  @value Order<KeyValue<#k, any>> order    new (order) {     if (!present(order)) {@@ -52,7 +52,7 @@    next () {     scoped {-      optional Order<KeyValue<#k,any>> order2 <- order.next()+      optional Order<KeyValue<#k, any>> order2 <- order.next()     } in if (present(order2)) {       order <- require(order2)       return self@@ -69,7 +69,7 @@ define MapValueOrder {   refines Order<#v> -  @value Order<KeyValue<any,#v>> order+  @value Order<KeyValue<any, #v>> order    new (order) {     if (!present(order)) {@@ -81,7 +81,7 @@    next () {     scoped {-      optional Order<KeyValue<any,#v>> order2 <- order.next()+      optional Order<KeyValue<any, #v>> order2 <- order.next()     } in if (present(order2)) {       order <- require(order2)       return self
lib/container/test/hashed-map.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,19 +17,19 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "HashedMap tests" {-  success+  success TestChecker }  unittest integrationTest {-  HashedMap<Int,Int> map <- HashedMap<Int,Int>.default()+  HashedMap<Int, Int> map <- HashedMap<Int, Int>.default()   Int count <- 33   $ReadOnly[count]$    // Insert values.   traverse (Counter.zeroIndexed(count) -> Int i) {     Int new <- ((i + 13) * 3547) % count-    \ map.set(new,i)-    \ Testing.checkEquals(map.size(),i+1)+    \ map.set(new, i)+    \ map.size() `Matches:with` CheckValue:equals(i+1)   }    // Check and remove values.@@ -55,21 +55,21 @@           .flush()     }     \ map.remove(new)-    \ Testing.checkEquals(map.size(),count-i-1)+    \ map.size() `Matches:with` CheckValue:equals(count-i-1)   } }  unittest removeNotPresent {-  HashedMap<Int,Int> map <- HashedMap<Int,Int>.new().set(1,1).set(2,2).set(4,4)+  HashedMap<Int, Int> map <- HashedMap<Int, Int>.new().set(1, 1).set(2, 2).set(4, 4)   \ map.remove(3)-  \ Testing.checkEquals(map.size(),3)+  \ map.size() `Matches:with` CheckValue:equals(3) }  unittest defaultOrder {-  HashedMap<Int,Int> map <- HashedMap<Int,Int>.new()+  HashedMap<Int, Int> map <- HashedMap<Int, Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the map in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -80,27 +80,27 @@    // Validate traversal coverage.   Int index <- 0-  traverse (map.defaultOrder() -> KeyValue<Int,Int> entry) {-    \ Testing.checkFalse(visited.readAt(entry.getKey()))-    \ Testing.checkEquals((entry.getValue()*hash)%max,entry.getKey())-    \ visited.writeAt(entry.getKey(),true)+  traverse (map.defaultOrder() -> KeyValue<Int, Int> entry) {+    \ visited.readAt(entry.getKey()) `Matches:with` CheckValue:equals(false)+    \ (entry.getValue()*hash)%max `Matches:with` CheckValue:equals(entry.getKey())+    \ visited.writeAt(entry.getKey(), true)     index <- index+1   } -  \ Testing.checkEquals(index,max)+  \ index `Matches:with` CheckValue:equals(max) }  unittest defaultOrderEmpty {-  traverse (HashedMap<Int,Int>.new().defaultOrder() -> _) {+  traverse (HashedMap<Int, Int>.new().defaultOrder() -> _) {     fail("not empty")   } }  unittest keyOrder {-  HashedMap<Int,Int> map <- HashedMap<Int,Int>.new()+  HashedMap<Int, Int> map <- HashedMap<Int, Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the map in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -112,19 +112,19 @@   // Validate traversal coverage.   Int index <- 0   traverse (map.keyOrder() -> Int key) {-    \ Testing.checkFalse(visited.readAt(key))-    \ visited.writeAt(key,true)+    \ visited.readAt(key) `Matches:with` CheckValue:equals(false)+    \ visited.writeAt(key, true)     index <- index+1   } -  \ Testing.checkEquals(index,max)+  \ index `Matches:with` CheckValue:equals(max) }  unittest valueOrder {-  HashedMap<Int,Int> map <- HashedMap<Int,Int>.new()+  HashedMap<Int, Int> map <- HashedMap<Int, Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the map in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -136,83 +136,92 @@   // Validate traversal coverage.   Int index <- 0   traverse (map.valueOrder() -> Int value) {-    \ Testing.checkFalse(visited.readAt(value))-    \ visited.writeAt(value,true)+    \ visited.readAt(value) `Matches:with` CheckValue:equals(false)+    \ visited.writeAt(value, true)     index <- index+1   } -  \ Testing.checkEquals(index,max)+  \ index `Matches:with` CheckValue:equals(max) }  unittest duplicate {-  HashedMap<Int,Int> map <- HashedMap<Int,Int>.default()+  HashedMap<Int, Int> map <- HashedMap<Int, Int>.default()   Int max <- 31   $ReadOnly[max]$    traverse (Counter.zeroIndexed(max) -> Int i) {-    \ map.set(i,i)+    \ map.set(i, i)   } -  HashedMap<Int,Int> copy <- map.duplicate()-  \ Testing.checkEquals(copy.size(),map.size())+  HashedMap<Int, Int> copy <- map.duplicate()+  \ copy.size() `Matches:with` CheckValue:equals(map.size())   traverse (Counter.zeroIndexed(max) -> Int i) {     $Hidden[map]$-    \ Testing.checkOptional(copy.get(i),i)+    \ copy.get(i) `Matches:with` CheckValue:equals(i)   } -  \ copy.set(2,5)+  \ copy.set(2, 5)   \ copy.remove(7)   $Hidden[copy]$ -  \ Testing.checkEquals(map.size(),max)+  \ map.size() `Matches:with` CheckValue:equals(max)   traverse (Counter.zeroIndexed(max) -> Int i) {-    \ Testing.checkOptional(map.get(i),i)+    \ map.get(i) `Matches:with` CheckValue:equals(i)   } }  unittest duplicateEmpty {-  HashedMap<Int,Int> map <- HashedMap<Int,Int>.new()-  HashedMap<Int,Int> copy <- map.duplicate()-  \ map.set(1,1)-  \ Testing.checkEquals(copy.size(),0)+  HashedMap<Int, Int> map <- HashedMap<Int, Int>.new()+  HashedMap<Int, Int> copy <- map.duplicate()+  \ map.set(1, 1)+  \ copy.size() `Matches:with` CheckValue:equals(0) }  unittest weakSetExists {-  HashedMap<Int,Value> map <- HashedMap<Int,Value>.default()-      .set(1,Value.new(1))-      .set(2,Value.new(2))-      .set(3,Value.new(3))+  HashedMap<Int, Value> map <- HashedMap<Int, Value>.default()+      .set(1, Value.new(1))+      .set(2, Value.new(2))+      .set(3, Value.new(3))    Value value0 <- Value.new(5)-  Value value1 <- map.weakSet(1,value0)-  \ Testing.checkEquals(map.size(),3)+  Value value1 <- map.weakSet(1, value0)+  \ map.size() `Matches:with` CheckValue:equals(3) -  \ Testing.checkEquals(value0.get(),5)-  \ Testing.checkEquals(value1.get(),1)+  \ value0.get() `Matches:with` CheckValue:equals(5)+  \ value1.get() `Matches:with` CheckValue:equals(1)    \ value0.set(10)-  \ Testing.checkEquals(value1.get(),1)-  \ Testing.checkOptional(map.get(1),Value.new(1))+  \ value1.get() `Matches:with` CheckValue:equals(1)+  \ map.get(1) `Matches:with` CheckValue:equals(Value.new(1)) }  unittest weakSetMissing {-  HashedMap<Int,Value> map <- HashedMap<Int,Value>.default()-      .set(1,Value.new(1))-      .set(2,Value.new(2))-      .set(3,Value.new(3))+  HashedMap<Int, Value> map <- HashedMap<Int, Value>.default()+      .set(1, Value.new(1))+      .set(2, Value.new(2))+      .set(3, Value.new(3))    Value value0 <- Value.new(5)-  Value value1 <- map.weakSet(7,value0)-  \ Testing.checkEquals(map.size(),4)+  Value value1 <- map.weakSet(7, value0)+  \ map.size() `Matches:with` CheckValue:equals(4) -  \ Testing.checkEquals(value0.get(),5)-  \ Testing.checkEquals(value1.get(),5)+  \ value0.get() `Matches:with` CheckValue:equals(5)+  \ value1.get() `Matches:with` CheckValue:equals(5)    \ value0.set(10)-  \ Testing.checkEquals(value1.get(),10)-  \ Testing.checkOptional(map.get(7),Value.new(10))+  \ value1.get() `Matches:with` CheckValue:equals(10)+  \ map.get(7) `Matches:with` CheckValue:equals(Value.new(10)) } +unittest setMember {+  HashedMap<Int, Value> map <- HashedMap<Int, Value>.default()+      .set(1, Value.new(1))+      .set(2, Value.new(2))+      .set(3, Value.new(3))+  \ map.member(1) `Matches:with` CheckValue:equals(true)+  \ map.member(5) `Matches:with` CheckValue:equals(false)+}+ concrete Value {   defines Equals<Value>   refines Formatted@@ -233,7 +242,7 @@     return value.formatted()   } -  equals (x,y) {+  equals (x, y) {     return x.get() == y.get()   } }
lib/container/test/hashed-set.0rt view
@@ -17,19 +17,19 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "HashedSet tests" {-  success+  success TestChecker }  unittest addAndRemove {   HashedSet<Int> set <- HashedSet<Int>.default()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the set in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {     \ set.add((i*hash)%max)-    \ Testing.checkEquals(set.size(),i+1)+    \ set.size() `Matches:with` CheckValue:equals(i+1)   }    // Remove only the odd elements.@@ -38,33 +38,33 @@       // Remove it twice to ensure idempotence.       \ set.remove(i).remove(i)     }-    \ Testing.checkEquals(set.size(),max-(i+1)/2)+    \ set.size() `Matches:with` CheckValue:equals(max-(i+1)/2)   }    // Validate set membership.   traverse (Counter.zeroIndexed(max) -> Int i) {-    \ Testing.checkEquals(set.member(i),i%2 == 0)+    \ set.member(i) `Matches:with` CheckValue:equals(i%2 == 0)   } }  unittest append {   HashedSet<Int> set <- HashedSet<Int>.new()   \ set.append(3)-  \ Testing.checkEquals(set.size(),1)-  \ Testing.checkTrue(set.member(3))+  \ set.size() `Matches:with` CheckValue:equals(1)+  \ set.member(3) `Matches:with` CheckValue:equals(true) }  unittest removeNotPresent {   HashedSet<Int> set <- HashedSet<Int>.new().add(1).add(2).add(4)   \ set.remove(3)-  \ Testing.checkEquals(set.size(),3)+  \ set.size() `Matches:with` CheckValue:equals(3) }  unittest defaultOrder {   HashedSet<Int> set <- HashedSet<Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the set in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -76,12 +76,12 @@   // Validate traversal coverage.   Int index <- 0   traverse (set.defaultOrder() -> Int entry) {-    \ Testing.checkFalse(visited.readAt(entry))-    \ visited.writeAt(entry,true)+    \ visited.readAt(entry) `Matches:with` CheckValue:equals(false)+    \ visited.writeAt(entry, true)     index <- index+1   } -  \ Testing.checkEquals(index,max)+  \ index `Matches:with` CheckValue:equals(max) }  unittest defaultOrderEmpty {@@ -94,12 +94,12 @@   HashedSet<Int> set <- HashedSet<Int>.new().add(1).add(2)    HashedSet<Int> copy <- set.duplicate()-  \ Testing.checkEquals(copy.size(),2)-  \ Testing.checkTrue(copy.member(1))-  \ Testing.checkTrue(copy.member(1))+  \ copy.size() `Matches:with` CheckValue:equals(2)+  \ copy.member(1) `Matches:with` CheckValue:equals(true)+  \ copy.member(1) `Matches:with` CheckValue:equals(true)    \ copy.remove(2)-  \ Testing.checkEquals(copy.size(),1)-  \ Testing.checkTrue(copy.member(1))-  \ Testing.checkTrue(set.member(2))+  \ copy.size() `Matches:with` CheckValue:equals(1)+  \ copy.member(1) `Matches:with` CheckValue:equals(true)+  \ set.member(2) `Matches:with` CheckValue:equals(true) }
lib/container/test/helpers.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,83 +17,83 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "comparator helper tests" {-  success+  success TestChecker }  unittest keyValueHLessThan {-  \ Testing.checkFalse(KV.new(1,"a") `KeyValueH:lessThan` KV.new(1,"a"))-  \ Testing.checkTrue(KV.new(1,"a") `KeyValueH:lessThan` KV.new(1,"b"))-  \ Testing.checkFalse(KV.new(2,"a") `KeyValueH:lessThan` KV.new(1,"b"))-  \ Testing.checkTrue(KV.new(1,"b") `KeyValueH:lessThan` KV.new(2,"a"))+  \ (KV.new(1, "a") `KeyValueH:lessThan` KV.new(1, "a")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(1, "a") `KeyValueH:lessThan` KV.new(1, "b")) `Matches:with` CheckValue:equals(true)+  \ (KV.new(2, "a") `KeyValueH:lessThan` KV.new(1, "b")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(1, "b") `KeyValueH:lessThan` KV.new(2, "a")) `Matches:with` CheckValue:equals(true) }  unittest keyValueHLessThanWith {-  \ Testing.checkFalse(KV.new(1,"a") `KeyValueH:lessThanWith<?,?,Int,AlwaysEqual>` KV.new(1,"a"))-  \ Testing.checkFalse(KV.new(1,"a") `KeyValueH:lessThanWith<?,?,Int,AlwaysEqual>` KV.new(1,"b"))-  \ Testing.checkFalse(KV.new(2,"a") `KeyValueH:lessThanWith<?,?,Int,AlwaysEqual>` KV.new(1,"b"))-  \ Testing.checkTrue(KV.new(1,"b") `KeyValueH:lessThanWith<?,?,Int,AlwaysEqual>` KV.new(2,"a"))+  \ (KV.new(1, "a") `KeyValueH:lessThanWith<?, ?, Int, AlwaysEqual>` KV.new(1, "a")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(1, "a") `KeyValueH:lessThanWith<?, ?, Int, AlwaysEqual>` KV.new(1, "b")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(2, "a") `KeyValueH:lessThanWith<?, ?, Int, AlwaysEqual>` KV.new(1, "b")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(1, "b") `KeyValueH:lessThanWith<?, ?, Int, AlwaysEqual>` KV.new(2, "a")) `Matches:with` CheckValue:equals(true) -  \ Testing.checkFalse(KV.new(1,"a") `KeyValueH:lessThanWith<?,?,AlwaysEqual,String>` KV.new(1,"a"))-  \ Testing.checkTrue(KV.new(1,"a") `KeyValueH:lessThanWith<?,?,AlwaysEqual,String>` KV.new(1,"b"))-  \ Testing.checkTrue(KV.new(2,"a") `KeyValueH:lessThanWith<?,?,AlwaysEqual,String>` KV.new(1,"b"))-  \ Testing.checkFalse(KV.new(1,"b") `KeyValueH:lessThanWith<?,?,AlwaysEqual,String>` KV.new(2,"a"))+  \ (KV.new(1, "a") `KeyValueH:lessThanWith<?, ?, AlwaysEqual, String>` KV.new(1, "a")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(1, "a") `KeyValueH:lessThanWith<?, ?, AlwaysEqual, String>` KV.new(1, "b")) `Matches:with` CheckValue:equals(true)+  \ (KV.new(2, "a") `KeyValueH:lessThanWith<?, ?, AlwaysEqual, String>` KV.new(1, "b")) `Matches:with` CheckValue:equals(true)+  \ (KV.new(1, "b") `KeyValueH:lessThanWith<?, ?, AlwaysEqual, String>` KV.new(2, "a")) `Matches:with` CheckValue:equals(false) }  unittest keyValueHEquals {-  \ Testing.checkTrue(KV.new(1,"a") `KeyValueH:equals` KV.new(1,"a"))-  \ Testing.checkFalse(KV.new(1,"a") `KeyValueH:equals` KV.new(1,"b"))-  \ Testing.checkFalse(KV.new(2,"a") `KeyValueH:equals` KV.new(1,"b"))-  \ Testing.checkFalse(KV.new(1,"b") `KeyValueH:equals` KV.new(2,"a"))+  \ (KV.new(1, "a") `KeyValueH:equals` KV.new(1, "a")) `Matches:with` CheckValue:equals(true)+  \ (KV.new(1, "a") `KeyValueH:equals` KV.new(1, "b")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(2, "a") `KeyValueH:equals` KV.new(1, "b")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(1, "b") `KeyValueH:equals` KV.new(2, "a")) `Matches:with` CheckValue:equals(false) }  unittest keyValueHEqualsWith {-  \ Testing.checkTrue(KV.new(1,"a") `KeyValueH:equalsWith<?,?,Int,AlwaysEqual>` KV.new(1,"a"))-  \ Testing.checkTrue(KV.new(1,"a") `KeyValueH:equalsWith<?,?,Int,AlwaysEqual>` KV.new(1,"b"))-  \ Testing.checkFalse(KV.new(2,"a") `KeyValueH:equalsWith<?,?,Int,AlwaysEqual>` KV.new(1,"b"))-  \ Testing.checkFalse(KV.new(1,"b") `KeyValueH:equalsWith<?,?,Int,AlwaysEqual>` KV.new(2,"a"))+  \ (KV.new(1, "a") `KeyValueH:equalsWith<?, ?, Int, AlwaysEqual>` KV.new(1, "a")) `Matches:with` CheckValue:equals(true)+  \ (KV.new(1, "a") `KeyValueH:equalsWith<?, ?, Int, AlwaysEqual>` KV.new(1, "b")) `Matches:with` CheckValue:equals(true)+  \ (KV.new(2, "a") `KeyValueH:equalsWith<?, ?, Int, AlwaysEqual>` KV.new(1, "b")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(1, "b") `KeyValueH:equalsWith<?, ?, Int, AlwaysEqual>` KV.new(2, "a")) `Matches:with` CheckValue:equals(false) -  \ Testing.checkTrue(KV.new(1,"a") `KeyValueH:equalsWith<?,?,AlwaysEqual,String>` KV.new(1,"a"))-  \ Testing.checkFalse(KV.new(1,"a") `KeyValueH:equalsWith<?,?,AlwaysEqual,String>` KV.new(1,"b"))-  \ Testing.checkFalse(KV.new(2,"a") `KeyValueH:equalsWith<?,?,AlwaysEqual,String>` KV.new(1,"b"))-  \ Testing.checkFalse(KV.new(1,"b") `KeyValueH:equalsWith<?,?,AlwaysEqual,String>` KV.new(2,"a"))+  \ (KV.new(1, "a") `KeyValueH:equalsWith<?, ?, AlwaysEqual, String>` KV.new(1, "a")) `Matches:with` CheckValue:equals(true)+  \ (KV.new(1, "a") `KeyValueH:equalsWith<?, ?, AlwaysEqual, String>` KV.new(1, "b")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(2, "a") `KeyValueH:equalsWith<?, ?, AlwaysEqual, String>` KV.new(1, "b")) `Matches:with` CheckValue:equals(false)+  \ (KV.new(1, "b") `KeyValueH:equalsWith<?, ?, AlwaysEqual, String>` KV.new(2, "a")) `Matches:with` CheckValue:equals(false) }  unittest integrationTest {-  SortedMap<Int,String> map1 <- SortedMap<Int,String>.new()-      .set(1,"d").set(2,"c").set(3,"b").set(4,"a")-  SortedMap<Int,String> map2 <- SortedMap<Int,String>.new()-      .set(1,"a").set(2,"b").set(3,"c").set(4,"d")+  SortedMap<Int, String> map1 <- SortedMap<Int, String>.new()+      .set(1, "d").set(2, "c").set(3, "b").set(4, "a")+  SortedMap<Int, String> map2 <- SortedMap<Int, String>.new()+      .set(1, "a").set(2, "b").set(3, "c").set(4, "d") -  \ Testing.checkTrue(map1.defaultOrder() `OrderH:equalsWith<?,KVEquals<Int,AlwaysEqual>>`    map2.defaultOrder())-  \ Testing.checkFalse(map1.defaultOrder() `OrderH:equalsWith<?,KVEquals<Int,String>>`         map2.defaultOrder())-  \ Testing.checkFalse(map1.defaultOrder() `OrderH:equalsWith<?,KVEquals<AlwaysEqual,String>>` map2.defaultOrder())+  \ (map1.defaultOrder() `OrderH:equalsWith<?, KVEquals<Int, AlwaysEqual>>`    map2.defaultOrder()) `Matches:with` CheckValue:equals(true)+  \ (map1.defaultOrder() `OrderH:equalsWith<?, KVEquals<Int, String>>`         map2.defaultOrder()) `Matches:with` CheckValue:equals(false)+  \ (map1.defaultOrder() `OrderH:equalsWith<?, KVEquals<AlwaysEqual, String>>` map2.defaultOrder()) `Matches:with` CheckValue:equals(false) } -concrete KVEquals<#k,#v> {-  defines Equals<KeyValue<Int,String>>+concrete KVEquals<#k, #v> {+  defines Equals<KeyValue<Int, String>>   #k defines Equals<Int>   #v defines Equals<String> }  define KVEquals {-  equals (x,y) {-    return x `KeyValueH:equalsWith<?,?,#k,#v>` y+  equals (x, y) {+    return x `KeyValueH:equalsWith<?, ?, #k, #v>` y   } }  concrete KV {-  refines KeyValue<Int,String>+  refines KeyValue<Int, String> -  @type new (Int,String) -> (KV)+  @type new (Int, String) -> (KV) }  define KV {-  $ReadOnly[key,value]$+  $ReadOnly[key, value]$    @value Int key   @value String value -  new (k,v) {+  new (k, v) {     return KV{ k, v }   } 
lib/container/test/list.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,7 +17,7 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "basic list tests" {-  success+  success TestChecker   timeout 5 } @@ -40,11 +40,11 @@       .append(4)    traverse (expected.defaultOrder() -> Int value) {-    \ Testing.checkEquals(require(head).get(),value)+    \ require(head).get() `Matches:with` CheckValue:equals(value)   } update {     head <- require(head).next()   }-  \ Testing.checkFalse(present(head))+  \ present(head) `Matches:with` CheckValue:equals(false) }  unittest reverseTraverse {@@ -67,11 +67,11 @@       .append(3)    traverse (expected.defaultOrder() -> Int value) {-    \ Testing.checkEquals(require(tail).get(),value)+    \ require(tail).get() `Matches:with` CheckValue:equals(value)   } update {     tail <- require(tail).prev()   }-  \ Testing.checkFalse(present(tail))+  \ present(tail) `Matches:with` CheckValue:equals(false) }  unittest setNext {@@ -84,7 +84,7 @@       .append(4)       .build() -  optional LinkedNode<Int> after1  <- Helper.jumpBy(3,head1)+  optional LinkedNode<Int> after1  <- Helper.jumpBy(3, head1)   optional LinkedNode<Int> before1 <- require(after1).prev()    optional LinkedNode<Int> head2, _ <- LinkedNode<Int>.builder()@@ -96,15 +96,15 @@       .append(14)       .build() -  optional LinkedNode<Int> after2  <- Helper.jumpBy(3,head2)+  optional LinkedNode<Int> after2  <- Helper.jumpBy(3, head2)   optional LinkedNode<Int> before2 <- require(after2).prev() -  \ Testing.checkEquals(require(require(before1).setNext(after2)).get(),1)+  \ require(require(before1).setNext(after2)).get() `Matches:with` CheckValue:equals(1) -  \ Testing.checkFalse(present(require(after1).prev()))-  \ Testing.checkEquals(require(require(before1).next()).get(),11)-  \ Testing.checkEquals(require(require(after2).prev()).get(),5)-  \ Testing.checkFalse(present(require(before2).next()))+  \ present(require(after1).prev()) `Matches:with` CheckValue:equals(false)+  \ require(require(before1).next()).get() `Matches:with` CheckValue:equals(11)+  \ require(require(after2).prev()).get() `Matches:with` CheckValue:equals(5)+  \ present(require(before2).next()) `Matches:with` CheckValue:equals(false) }  unittest setPrev {@@ -117,7 +117,7 @@       .append(4)       .build() -  optional LinkedNode<Int> after1  <- Helper.jumpBy(3,head1)+  optional LinkedNode<Int> after1  <- Helper.jumpBy(3, head1)   optional LinkedNode<Int> before1 <- require(after1).prev()    optional LinkedNode<Int> head2, _ <- LinkedNode<Int>.builder()@@ -129,15 +129,15 @@       .append(14)       .build() -  optional LinkedNode<Int> after2  <- Helper.jumpBy(3,head2)+  optional LinkedNode<Int> after2  <- Helper.jumpBy(3, head2)   optional LinkedNode<Int> before2 <- require(after2).prev() -  \ Testing.checkEquals(require(require(after1).setPrev(before2)).get(),5)+  \ require(require(after1).setPrev(before2)).get() `Matches:with` CheckValue:equals(5) -  \ Testing.checkEquals(require(require(after1).prev()).get(),15)-  \ Testing.checkFalse(present(require(before1).next()))-  \ Testing.checkFalse(present(require(after2).prev()))-  \ Testing.checkEquals(require(require(before2).next()).get(),1)+  \ require(require(after1).prev()).get() `Matches:with` CheckValue:equals(15)+  \ present(require(before1).next()) `Matches:with` CheckValue:equals(false)+  \ present(require(after2).prev()) `Matches:with` CheckValue:equals(false)+  \ require(require(before2).next()).get() `Matches:with` CheckValue:equals(1) }  unittest setNextSame {@@ -150,13 +150,13 @@       .append(4)       .build() -  optional LinkedNode<Int> after  <- Helper.jumpBy(3,head)+  optional LinkedNode<Int> after  <- Helper.jumpBy(3, head)   optional LinkedNode<Int> before <- require(after).prev()    \ require(before).setNext(after) -  \ Testing.checkEquals(require(require(after).prev()).get(),5)-  \ Testing.checkEquals(require(require(before).next()).get(),1)+  \ require(require(after).prev()).get() `Matches:with` CheckValue:equals(5)+  \ require(require(before).next()).get() `Matches:with` CheckValue:equals(1) }  unittest setPrevSame {@@ -169,13 +169,13 @@       .append(4)       .build() -  optional LinkedNode<Int> after  <- Helper.jumpBy(3,head)+  optional LinkedNode<Int> after  <- Helper.jumpBy(3, head)   optional LinkedNode<Int> before <- require(after).prev()    \ require(after).setPrev(before) -  \ Testing.checkEquals(require(require(after).prev()).get(),5)-  \ Testing.checkEquals(require(require(before).next()).get(),1)+  \ require(require(after).prev()).get() `Matches:with` CheckValue:equals(5)+  \ require(require(before).next()).get() `Matches:with` CheckValue:equals(1) }  unittest setNextSelf {@@ -188,14 +188,14 @@       .append(4)       .build() -  optional LinkedNode<Int> after  <- Helper.jumpBy(3,head)+  optional LinkedNode<Int> after  <- Helper.jumpBy(3, head)   optional LinkedNode<Int> before <- require(after).prev()    \ require(before).setNext(before) -  \ Testing.checkFalse(present(require(after).prev()))-  \ Testing.checkEquals(require(require(before).prev()).get(),5)-  \ Testing.checkEquals(require(require(before).next()).get(),5)+  \ present(require(after).prev()) `Matches:with` CheckValue:equals(false)+  \ require(require(before).prev()).get() `Matches:with` CheckValue:equals(5)+  \ require(require(before).next()).get() `Matches:with` CheckValue:equals(5) }  unittest setPrevSelf {@@ -208,14 +208,14 @@       .append(4)       .build() -  optional LinkedNode<Int> after  <- Helper.jumpBy(3,head)+  optional LinkedNode<Int> after  <- Helper.jumpBy(3, head)   optional LinkedNode<Int> before <- require(after).prev()    \ require(after).setPrev(after) -  \ Testing.checkFalse(present(require(before).next()))-  \ Testing.checkEquals(require(require(after).prev()).get(),1)-  \ Testing.checkEquals(require(require(after).next()).get(),1)+  \ present(require(before).next()) `Matches:with` CheckValue:equals(false)+  \ require(require(after).prev()).get() `Matches:with` CheckValue:equals(1)+  \ require(require(after).next()).get() `Matches:with` CheckValue:equals(1) }  unittest duplicate {@@ -237,20 +237,20 @@       .append(4)    optional LinkedNode<Int> head2 <- require(head).duplicate()-  \ require(Helper.jumpBy(3,head)).set(7).setNext(empty)+  \ require(Helper.jumpBy(3, head)).set(7).setNext(empty)   $Hidden[head]$    traverse (expected.defaultOrder() -> Int value) {-    \ Testing.checkEquals(require(head2).get(),value)+    \ require(head2).get() `Matches:with` CheckValue:equals(value)   } update {     head2 <- require(head2).next()   }-  \ Testing.checkFalse(present(head2))+  \ present(head2) `Matches:with` CheckValue:equals(false) }  unittest hugeCleanup { $DisableCoverage$   scoped {-    ListBuilder<Int,LinkedNode<Int>> builder <- LinkedNode<Int>.builder()+    ListBuilder<Int, LinkedNode<Int>> builder <- LinkedNode<Int>.builder()   } in traverse (Counter.zeroIndexed(1000000) -> _) {     \ builder.append(0)   }@@ -275,11 +275,11 @@       .append(4)    traverse (expected.defaultOrder() -> Int value) {-    \ Testing.checkEquals(require(head).get(),value)+    \ require(head).get() `Matches:with` CheckValue:equals(value)   } update {     head <- require(head).next()   }-  \ Testing.checkFalse(present(head))+  \ present(head) `Matches:with` CheckValue:equals(false) }  unittest duplicateSingle {@@ -301,20 +301,20 @@       .append(4)    optional ForwardNode<Int> head2 <- require(head).duplicate()-  \ require(Helper.jumpBy(3,head)).set(7).setNext(empty)+  \ require(Helper.jumpBy(3, head)).set(7).setNext(empty)   $Hidden[head]$    traverse (expected.defaultOrder() -> Int value) {-    \ Testing.checkEquals(require(head2).get(),value)+    \ require(head2).get() `Matches:with` CheckValue:equals(value)   } update {     head2 <- require(head2).next()   }-  \ Testing.checkFalse(present(head2))+  \ present(head2) `Matches:with` CheckValue:equals(false) }  unittest hugeCleanupSingle { $DisableCoverage$   scoped {-    ListBuilder<Int,ForwardNode<Int>> builder <- ForwardNode<Int>.builder()+    ListBuilder<Int, ForwardNode<Int>> builder <- ForwardNode<Int>.builder()   } in traverse (Counter.zeroIndexed(1000000) -> _) {     \ builder.append(0)   }@@ -323,11 +323,11 @@ concrete Helper {   @type jumpBy<#x>     #x requires Order<any>-  (Int,optional #x) -> (optional #x)+  (Int, optional #x) -> (optional #x) }  define Helper {-  jumpBy (n,x) (y) {+  jumpBy (n, x) (y) {     y <- x     traverse (Counter.zeroIndexed(n) -> _) {       y <- require(y).next()
lib/container/test/queue.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,7 +17,7 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "SimpleQueue tests" {-  success+  success TestChecker }  unittest integrationTest {@@ -25,14 +25,14 @@   $ReadOnly[max]$   SimpleQueue<Int> queue <- SimpleQueue<Int>.default()   traverse (`Counter.zeroIndexed` max -> Int value) {-    \ Testing.checkEquals(queue.size(),value)+    \ queue.size() `Matches:with` CheckValue:equals(value)     \ queue.append(value)   }   traverse (`Counter.zeroIndexed` max -> Int value) {-    \ Testing.checkEquals(queue.size(),max-value)-    \ Testing.checkEquals(queue.pop(),value)+    \ queue.size() `Matches:with` CheckValue:equals(max-value)+    \ queue.pop() `Matches:with` CheckValue:equals(value)   }-  \ Testing.checkEquals(queue.size(),0)+  \ queue.size() `Matches:with` CheckValue:equals(0) }  unittest duplicate {@@ -45,8 +45,8 @@   \ queue.pop()   $Hidden[queue]$   traverse (`Counter.zeroIndexed` max -> Int value) {-    \ Testing.checkEquals(copy.size(),max-value)-    \ Testing.checkEquals(copy.pop(),value)+    \ copy.size() `Matches:with` CheckValue:equals(max-value)+    \ copy.pop() `Matches:with` CheckValue:equals(value)   }-  \ Testing.checkEquals(copy.size(),0)+  \ copy.size() `Matches:with` CheckValue:equals(0) }
lib/container/test/sorted-map.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -17,19 +17,19 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "SortedMap tests" {-  success+  success TestChecker }  unittest integrationTest {-  ValidatedTree<Int,Int> map <- ValidatedTree<Int,Int>.new()+  ValidatedTree<Int, Int> map <- ValidatedTree<Int, Int>.new()   Int count <- 33   $ReadOnly[count]$    // Insert values.   traverse (Counter.zeroIndexed(count) -> Int i) {     Int new <- ((i + 13) * 3547) % count-    \ map.set(new,i)-    \ Testing.checkEquals(map.size(),i+1)+    \ map.set(new, i)+    \ map.size() `Matches:with` CheckValue:equals(i+1)   }    // Check and remove values.@@ -55,21 +55,21 @@           .flush()     }     \ map.remove(new)-    \ Testing.checkEquals(map.size(),count-i-1)+    \ map.size() `Matches:with` CheckValue:equals(count-i-1)   } }  unittest removeNotPresent {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new().set(1,1).set(2,2).set(4,4)+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new().set(1, 1).set(2, 2).set(4, 4)   \ map.remove(3)-  \ Testing.checkEquals(map.size(),3)+  \ map.size() `Matches:with` CheckValue:equals(3) }  unittest defaultOrder {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new()+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the map in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -78,26 +78,26 @@    // Validate the traversal order.   Int index <- 0-  traverse (map.defaultOrder() -> KeyValue<Int,Int> entry) {-    \ Testing.checkEquals(entry.getKey(),index)-    \ Testing.checkEquals((entry.getValue()*hash)%max,entry.getKey())+  traverse (map.defaultOrder() -> KeyValue<Int, Int> entry) {+    \ entry.getKey() `Matches:with` CheckValue:equals(index)+    \ (entry.getValue()*hash)%max `Matches:with` CheckValue:equals(entry.getKey())     index <- index+1   } -  \ Testing.checkEquals(index,max)+  \ index `Matches:with` CheckValue:equals(max) }  unittest defaultOrderEmpty {-  traverse (SortedMap<Int,Int>.new().defaultOrder() -> _) {+  traverse (SortedMap<Int, Int>.new().defaultOrder() -> _) {     fail("not empty")   } }  unittest keyOrder {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new()+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the map in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -107,18 +107,18 @@   // Validate the traversal order.   Int index <- 0   traverse (map.keyOrder() -> Int key) {-    \ Testing.checkEquals(key,index)+    \ key `Matches:with` CheckValue:equals(index)     index <- index+1   } -  \ Testing.checkEquals(index,max)+  \ index `Matches:with` CheckValue:equals(max) }  unittest valueOrder {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new()+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the map in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -128,18 +128,18 @@   // Validate the traversal order.   Int index <- 0   traverse (map.valueOrder() -> Int value) {-    \ Testing.checkEquals((value*hash)%max,index)+    \ (value*hash)%max `Matches:with` CheckValue:equals(index)     index <- index+1   } -  \ Testing.checkEquals(index,max)+  \ index `Matches:with` CheckValue:equals(max) }  unittest reverseOrder {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new()+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the map in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -148,20 +148,20 @@    // Validate the traversal order.   Int index <- max-  traverse (map.reverseOrder() -> KeyValue<Int,Int> entry) {+  traverse (map.reverseOrder() -> KeyValue<Int, Int> entry) {     index <- index-1-    \ Testing.checkEquals(entry.getKey(),index)-    \ Testing.checkEquals((entry.getValue()*hash)%max,entry.getKey())+    \ entry.getKey() `Matches:with` CheckValue:equals(index)+    \ (entry.getValue()*hash)%max `Matches:with` CheckValue:equals(entry.getKey())   } -  \ Testing.checkEquals(index,0)+  \ index `Matches:with` CheckValue:equals(0) }  unittest getForward {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new()+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the map in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -171,39 +171,39 @@   // Validate the traversal order from every starting point.   traverse (Counter.zeroIndexed(max) -> Int i) {     Int index <- i-    traverse (map.getForward(index) -> KeyValue<Int,Int> entry) {-      \ Testing.checkEquals(entry.getKey(),index)-      \ Testing.checkEquals((entry.getValue()*hash)%max,entry.getKey())+    traverse (map.getForward(index) -> KeyValue<Int, Int> entry) {+      \ entry.getKey() `Matches:with` CheckValue:equals(index)+      \ (entry.getValue()*hash)%max `Matches:with` CheckValue:equals(entry.getKey())       index <- index+1     }-    \ Testing.checkEquals(index,max)+    \ index `Matches:with` CheckValue:equals(max)   } }  unittest getForwardNotFound {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new()-  \ map.set(1,1).set(3,3).set(5,5)+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new()+  \ map.set(1, 1).set(3, 3).set(5, 5)    scoped {-    optional Order<KeyValue<Int,Int>> start <- map.getForward(4)+    optional Order<KeyValue<Int, Int>> start <- map.getForward(4)   } in if (!present(start)) {     fail("Failed")   } else {-    \ Testing.checkEquals(require(start).get().getKey(),5)+    \ require(start).get().getKey() `Matches:with` CheckValue:equals(5)   }    scoped {-    optional Order<KeyValue<Int,Int>> start <- map.getForward(6)+    optional Order<KeyValue<Int, Int>> start <- map.getForward(6)   } in if (present(start)) {     fail("Failed")   } }  unittest getReverse {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new()+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the map in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -213,103 +213,112 @@   // Validate the traversal order from every starting point.   traverse (Counter.zeroIndexed(max) -> Int i) {     Int index <- i-    traverse (map.getReverse(index) -> KeyValue<Int,Int> entry) {-      \ Testing.checkEquals(entry.getKey(),index)-      \ Testing.checkEquals((entry.getValue()*hash)%max,entry.getKey())+    traverse (map.getReverse(index) -> KeyValue<Int, Int> entry) {+      \ entry.getKey() `Matches:with` CheckValue:equals(index)+      \ (entry.getValue()*hash)%max `Matches:with` CheckValue:equals(entry.getKey())       index <- index-1     }-    \ Testing.checkEquals(index,-1)+    \ index `Matches:with` CheckValue:equals(-1)   } }  unittest getReverseNotFound {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new()-  \ map.set(1,1).set(3,3).set(5,5)+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new()+  \ map.set(1, 1).set(3, 3).set(5, 5)    scoped {-    optional Order<KeyValue<Int,Int>> start <- map.getReverse(2)+    optional Order<KeyValue<Int, Int>> start <- map.getReverse(2)   } in if (!present(start)) {     fail("Failed")   } else {-    \ Testing.checkEquals(require(start).get().getKey(),1)+    \ require(start).get().getKey() `Matches:with` CheckValue:equals(1)   }    scoped {-    optional Order<KeyValue<Int,Int>> start <- map.getReverse(0)+    optional Order<KeyValue<Int, Int>> start <- map.getReverse(0)   } in if (present(start)) {     fail("Failed")   } }  unittest duplicate {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.default()+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.default()   Int max <- 31   $ReadOnly[max]$    traverse (Counter.zeroIndexed(max) -> Int i) {-    \ map.set(i,i)+    \ map.set(i, i)   } -  SortedMap<Int,Int> copy <- map.duplicate()-  \ Testing.checkEquals(copy.size(),map.size())+  SortedMap<Int, Int> copy <- map.duplicate()+  \ copy.size() `Matches:with` CheckValue:equals(map.size())   traverse (Counter.zeroIndexed(max) -> Int i) {     $Hidden[map]$-    \ Testing.checkOptional(copy.get(i),i)+    \ copy.get(i) `Matches:with` CheckValue:equals(i)   } -  \ copy.set(2,5)+  \ copy.set(2, 5)   \ copy.remove(7)   $Hidden[copy]$ -  \ Testing.checkEquals(map.size(),max)+  \ map.size() `Matches:with` CheckValue:equals(max)   traverse (Counter.zeroIndexed(max) -> Int i) {-    \ Testing.checkOptional(map.get(i),i)+    \ map.get(i) `Matches:with` CheckValue:equals(i)   } }  unittest duplicateEmpty {-  SortedMap<Int,Int> map <- SortedMap<Int,Int>.new()-  SortedMap<Int,Int> copy <- map.duplicate()-  \ map.set(1,1)-  \ Testing.checkEquals(copy.size(),0)+  SortedMap<Int, Int> map <- SortedMap<Int, Int>.new()+  SortedMap<Int, Int> copy <- map.duplicate()+  \ map.set(1, 1)+  \ copy.size() `Matches:with` CheckValue:equals(0) }  unittest weakSetExists {-  SortedMap<Int,Value> map <- SortedMap<Int,Value>.default()-      .set(1,Value.new(1))-      .set(2,Value.new(2))-      .set(3,Value.new(3))+  SortedMap<Int, Value> map <- SortedMap<Int, Value>.default()+      .set(1, Value.new(1))+      .set(2, Value.new(2))+      .set(3, Value.new(3))    Value value0 <- Value.new(5)-  Value value1 <- map.weakSet(1,value0)-  \ Testing.checkEquals(map.size(),3)+  Value value1 <- map.weakSet(1, value0)+  \ map.size() `Matches:with` CheckValue:equals(3) -  \ Testing.checkEquals(value0.get(),5)-  \ Testing.checkEquals(value1.get(),1)+  \ value0.get() `Matches:with` CheckValue:equals(5)+  \ value1.get() `Matches:with` CheckValue:equals(1)    \ value0.set(10)-  \ Testing.checkEquals(value1.get(),1)-  \ Testing.checkOptional(map.get(1),Value.new(1))+  \ value1.get() `Matches:with` CheckValue:equals(1)+  \ map.get(1) `Matches:with` CheckValue:equals(Value.new(1)) }  unittest weakSetMissing {-  SortedMap<Int,Value> map <- SortedMap<Int,Value>.default()-      .set(1,Value.new(1))-      .set(2,Value.new(2))-      .set(3,Value.new(3))+  SortedMap<Int, Value> map <- SortedMap<Int, Value>.default()+      .set(1, Value.new(1))+      .set(2, Value.new(2))+      .set(3, Value.new(3))    Value value0 <- Value.new(5)-  Value value1 <- map.weakSet(7,value0)-  \ Testing.checkEquals(map.size(),4)+  Value value1 <- map.weakSet(7, value0)+  \ map.size() `Matches:with` CheckValue:equals(4) -  \ Testing.checkEquals(value0.get(),5)-  \ Testing.checkEquals(value1.get(),5)+  \ value0.get() `Matches:with` CheckValue:equals(5)+  \ value1.get() `Matches:with` CheckValue:equals(5)    \ value0.set(10)-  \ Testing.checkEquals(value1.get(),10)-  \ Testing.checkOptional(map.get(7),Value.new(10))+  \ value1.get() `Matches:with` CheckValue:equals(10)+  \ map.get(7) `Matches:with` CheckValue:equals(Value.new(10)) } +unittest setMember {+  SortedMap<Int, Value> map <- SortedMap<Int, Value>.default()+      .set(1, Value.new(1))+      .set(2, Value.new(2))+      .set(3, Value.new(3))+  \ map.member(1) `Matches:with` CheckValue:equals(true)+  \ map.member(5) `Matches:with` CheckValue:equals(false)+}+ concrete Value {   defines Equals<Value>   refines Formatted@@ -330,7 +339,7 @@     return value.formatted()   } -  equals (x,y) {+  equals (x, y) {     return x.get() == y.get()   } }
lib/container/test/sorted-set.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,19 +17,19 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "SortedSet tests" {-  success+  success TestChecker }  unittest addAndRemove {   SortedSet<Int> set <- SortedSet<Int>.default()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the set in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {     \ set.add((i*hash)%max)-    \ Testing.checkEquals(set.size(),i+1)+    \ set.size() `Matches:with` CheckValue:equals(i+1)   }    // Remove only the odd elements.@@ -38,33 +38,33 @@       // Remove it twice to ensure idempotence.       \ set.remove(i).remove(i)     }-    \ Testing.checkEquals(set.size(),max-(i+1)/2)+    \ set.size() `Matches:with` CheckValue:equals(max-(i+1)/2)   }    // Validate set membership.   traverse (Counter.zeroIndexed(max) -> Int i) {-    \ Testing.checkEquals(set.member(i),i%2 == 0)+    \ set.member(i) `Matches:with` CheckValue:equals(i%2 == 0)   } }  unittest append {   SortedSet<Int> set <- SortedSet<Int>.new()   \ set.append(3)-  \ Testing.checkEquals(set.size(),1)-  \ Testing.checkTrue(set.member(3))+  \ set.size() `Matches:with` CheckValue:equals(1)+  \ set.member(3) `Matches:with` CheckValue:equals(true) }  unittest removeNotPresent {   SortedSet<Int> set <- SortedSet<Int>.new().add(1).add(2).add(4)   \ set.remove(3)-  \ Testing.checkEquals(set.size(),3)+  \ set.size() `Matches:with` CheckValue:equals(3) }  unittest defaultOrder {   SortedSet<Int> set <- SortedSet<Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the set in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -74,11 +74,11 @@   // Validate the traversal order.   Int index <- 0   traverse (set.defaultOrder() -> Int entry) {-    \ Testing.checkEquals(entry,index)+    \ entry `Matches:with` CheckValue:equals(index)     index <- index+1   } -  \ Testing.checkEquals(index,max)+  \ index `Matches:with` CheckValue:equals(max) }  unittest defaultOrderEmpty {@@ -91,7 +91,7 @@   SortedSet<Int> set <- SortedSet<Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the set in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -102,17 +102,17 @@   Int index <- max   traverse (set.reverseOrder() -> Int entry) {     index <- index-1-    \ Testing.checkEquals(entry,index)+    \ entry `Matches:with` CheckValue:equals(index)   } -  \ Testing.checkEquals(index,0)+  \ index `Matches:with` CheckValue:equals(0) }  unittest getForward {   SortedSet<Int> set <- SortedSet<Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the set in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -123,10 +123,10 @@   traverse (Counter.zeroIndexed(max) -> Int i) {     Int index <- i     traverse (set.getForward(index) -> Int entry) {-      \ Testing.checkEquals(entry,index)+      \ entry `Matches:with` CheckValue:equals(index)       index <- index+1     }-    \ Testing.checkEquals(index,max)+    \ index `Matches:with` CheckValue:equals(max)   } } @@ -139,7 +139,7 @@   } in if (!present(start)) {     fail("Failed")   } else {-    \ Testing.checkEquals(require(start).get(),5)+    \ require(start).get() `Matches:with` CheckValue:equals(5)   }    scoped {@@ -153,7 +153,7 @@   SortedSet<Int> set <- SortedSet<Int>.new()   Int hash <- 13   Int max  <- 20-  $ReadOnly[hash,max]$+  $ReadOnly[hash, max]$    // Populate the set in a pseudo-random order.   traverse (Counter.zeroIndexed(max) -> Int i) {@@ -164,10 +164,10 @@   traverse (Counter.zeroIndexed(max) -> Int i) {     Int index <- i     traverse (set.getReverse(index) -> Int entry) {-      \ Testing.checkEquals(entry,index)+      \ entry `Matches:with` CheckValue:equals(index)       index <- index-1     }-    \ Testing.checkEquals(index,-1)+    \ index `Matches:with` CheckValue:equals(-1)   } } @@ -180,7 +180,7 @@   } in if (!present(start)) {     fail("Failed")   } else {-    \ Testing.checkEquals(require(start).get(),1)+    \ require(start).get() `Matches:with` CheckValue:equals(1)   }    scoped {@@ -194,12 +194,12 @@   SortedSet<Int> set <- SortedSet<Int>.new().add(1).add(2)    SortedSet<Int> copy <- set.duplicate()-  \ Testing.checkEquals(copy.size(),2)-  \ Testing.checkTrue(copy.member(1))-  \ Testing.checkTrue(copy.member(1))+  \ copy.size() `Matches:with` CheckValue:equals(2)+  \ copy.member(1) `Matches:with` CheckValue:equals(true)+  \ copy.member(1) `Matches:with` CheckValue:equals(true)    \ copy.remove(2)-  \ Testing.checkEquals(copy.size(),1)-  \ Testing.checkTrue(copy.member(1))-  \ Testing.checkTrue(set.member(2))+  \ copy.size() `Matches:with` CheckValue:equals(1)+  \ copy.member(1) `Matches:with` CheckValue:equals(true)+  \ set.member(2) `Matches:with` CheckValue:equals(true) }
lib/container/test/sorting.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,7 +17,7 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "Sorting tests" {-  success+  success TestChecker   timeout 5 } @@ -26,7 +26,7 @@   TestSequence expected <- TestSequence.create()   Int hash <- 269   Int size <- 137-  $ReadOnly[hash,size]$+  $ReadOnly[hash, size]$    traverse (Counter.zeroIndexed(size) -> Int i) {     \ original.append((i*hash)%size/3)@@ -34,7 +34,7 @@   }    \ Sorting:sort(original)-  \ Testing.checkEquals(original,expected)+  \ original `Matches:with` CheckValue:equals(expected) }  unittest sortWith { $DisableCoverage$@@ -42,15 +42,15 @@   TestSequence expected <- TestSequence.create()   Int hash <- 313   Int size <- 197-  $ReadOnly[hash,size]$+  $ReadOnly[hash, size]$    traverse (Counter.revZeroIndexed(size) -> Int i) {     \ original.append((i*hash)%size/3)     \ expected.append(i/3)   } -  \ Sorting:sortWith<?,Reversed<Int>>(original)-  \ Testing.checkEquals(original,expected)+  \ Sorting:sortWith<?, Reversed<Int>>(original)+  \ original `Matches:with` CheckValue:equals(expected) }  unittest sortEmpty {@@ -58,7 +58,7 @@   TestSequence expected <- TestSequence.create()    \ Sorting:sort(original)-  \ Testing.checkEquals(original,expected)+  \ original `Matches:with` CheckValue:equals(expected) }  unittest reverseEvenSize {@@ -76,7 +76,7 @@   }    \ Sorting:reverse(original)-  \ Testing.checkEquals(original,expected)+  \ original `Matches:with` CheckValue:equals(expected) }  unittest reverseOddSize { $DisableCoverage$@@ -94,7 +94,7 @@   }    \ Sorting:reverse(original)-  \ Testing.checkEquals(original,expected)+  \ original `Matches:with` CheckValue:equals(expected) }  unittest reverseEmpty {@@ -102,15 +102,15 @@   TestSequence expected <- TestSequence.create()    \ Sorting:reverse(original)-  \ Testing.checkEquals(original,expected)+  \ original `Matches:with` CheckValue:equals(expected) }  unittest sortList {-  ListBuilder<Int,LinkedNode<Int>> builder <- LinkedNode<Int>.builder()+  ListBuilder<Int, LinkedNode<Int>> builder <- LinkedNode<Int>.builder()   Vector<Int> expected <- Vector<Int>.new()   Int hash <- 269   Int size <- 137-  $ReadOnly[hash,size]$+  $ReadOnly[hash, size]$    traverse (Counter.zeroIndexed(size) -> Int i) {     \ builder.append((i*hash)%size/3)@@ -120,19 +120,19 @@   optional LinkedNode<Int> actual <- Sorting:sortList(builder.build(){0})    traverse (expected.defaultOrder() -> Int n) {-    \ Testing.checkEquals(require(actual).get(),n)+    \ require(actual).get() `Matches:with` CheckValue:equals(n)   } update {     actual <- require(actual).next()   }-  \ Testing.checkFalse(present(actual))+  \ present(actual) `Matches:with` CheckValue:equals(false) }  unittest sortListSingle { $DisableCoverage$-  ListBuilder<Int,ForwardNode<Int>> builder <- ForwardNode<Int>.builder()+  ListBuilder<Int, ForwardNode<Int>> builder <- ForwardNode<Int>.builder()   Vector<Int> expected <- Vector<Int>.new()   Int hash <- 269   Int size <- 137-  $ReadOnly[hash,size]$+  $ReadOnly[hash, size]$    traverse (Counter.zeroIndexed(size) -> Int i) {     \ builder.append((i*hash)%size/3)@@ -142,23 +142,23 @@   optional ForwardNode<Int> actual <- Sorting:sortList(builder.build(){0})    traverse (expected.defaultOrder() -> Int n) {-    \ Testing.checkEquals(require(actual).get(),n)+    \ require(actual).get() `Matches:with` CheckValue:equals(n)   } update {     actual <- require(actual).next()   }-  \ Testing.checkFalse(present(actual))+  \ present(actual) `Matches:with` CheckValue:equals(false) }  unittest sortListEmpty {-  \ Sorting:sortList<LinkedNode<Int>,Int>(empty)+  \ Sorting:sortList<LinkedNode<Int>, Int>(empty) }  unittest sortListPow2 { $DisableCoverage$-  ListBuilder<Int,LinkedNode<Int>> builder <- LinkedNode<Int>.builder()+  ListBuilder<Int, LinkedNode<Int>> builder <- LinkedNode<Int>.builder()   Vector<Int> expected <- Vector<Int>.new()   Int hash <- 269   Int size <- 256-  $ReadOnly[hash,size]$+  $ReadOnly[hash, size]$    traverse (Counter.zeroIndexed(size) -> Int i) {     \ builder.append((i*hash)%size/3)@@ -168,37 +168,37 @@   optional LinkedNode<Int> actual <- Sorting:sortList(builder.build(){0})    traverse (expected.defaultOrder() -> Int n) {-    \ Testing.checkEquals(require(actual).get(),n)+    \ require(actual).get() `Matches:with` CheckValue:equals(n)   } update {     actual <- require(actual).next()   }-  \ Testing.checkFalse(present(actual))+  \ present(actual) `Matches:with` CheckValue:equals(false) }  unittest sortListWith { $DisableCoverage$-  ListBuilder<Int,LinkedNode<Int>> builder <- LinkedNode<Int>.builder()+  ListBuilder<Int, LinkedNode<Int>> builder <- LinkedNode<Int>.builder()   Vector<Int> expected <- Vector<Int>.new()   Int hash <- 269   Int size <- 137-  $ReadOnly[hash,size]$+  $ReadOnly[hash, size]$    traverse (Counter.revZeroIndexed(size) -> Int i) {     \ builder.append((i*hash)%size/3)     \ expected.append(i/3)   } -  optional LinkedNode<Int> actual <- Sorting:sortListWith<?,?,Reversed<Int>>(builder.build(){0})+  optional LinkedNode<Int> actual <- Sorting:sortListWith<?, ?, Reversed<Int>>(builder.build(){0})    traverse (expected.defaultOrder() -> Int n) {-    \ Testing.checkEquals(require(actual).get(),n)+    \ require(actual).get() `Matches:with` CheckValue:equals(n)   } update {     actual <- require(actual).next()   }-  \ Testing.checkFalse(present(actual))+  \ present(actual) `Matches:with` CheckValue:equals(false) }  unittest reverseList {-  ListBuilder<Int,LinkedNode<Int>> builder <- LinkedNode<Int>.builder()+  ListBuilder<Int, LinkedNode<Int>> builder <- LinkedNode<Int>.builder()   Vector<Int> expected <- Vector<Int>.new()   Int size <- 101   $ReadOnly[size]$@@ -214,15 +214,15 @@   optional LinkedNode<Int> reversed <- Sorting:reverseList(builder.build(){0})    traverse (expected.defaultOrder() -> Int value) {-    \ Testing.checkEquals(require(reversed).get(),value)+    \ require(reversed).get() `Matches:with` CheckValue:equals(value)   } update {     reversed <- require(reversed).next()   }-  \ Testing.checkFalse(present(reversed))+  \ present(reversed) `Matches:with` CheckValue:equals(false) }  unittest reverseListSingle { $DisableCoverage$-  ListBuilder<Int,ForwardNode<Int>> builder <- ForwardNode<Int>.builder()+  ListBuilder<Int, ForwardNode<Int>> builder <- ForwardNode<Int>.builder()   Vector<Int> expected <- Vector<Int>.new()   Int size <- 101   $ReadOnly[size]$@@ -238,15 +238,15 @@   optional ForwardNode<Int> reversed <- Sorting:reverseList(builder.build(){0})    traverse (expected.defaultOrder() -> Int value) {-    \ Testing.checkEquals(require(reversed).get(),value)+    \ require(reversed).get() `Matches:with` CheckValue:equals(value)   } update {     reversed <- require(reversed).next()   }-  \ Testing.checkFalse(present(reversed))+  \ present(reversed) `Matches:with` CheckValue:equals(false) }  unittest reverseListEmpty {-  \ Sorting:reverseList<LinkedNode<Int>,Int>(empty)+  \ Sorting:reverseList<LinkedNode<Int>, Int>(empty) }  concrete TestSequence {@@ -267,7 +267,7 @@   }    formatted () {-    [Append<Formatted>&Build<String>] builder <- String.builder()+    [Append<Formatted> & Build<String>] builder <- String.builder()     \ builder.append("{")     traverse (seq.defaultOrder() -> Formatted x) {       \ builder.append(" ").append(x)@@ -283,8 +283,8 @@     return seq.readAt(i)   } -  writeAt (i,x) {-    \ seq.writeAt(i,x)+  writeAt (i, x) {+    \ seq.writeAt(i, x)     return self   } @@ -293,7 +293,7 @@     return self   } -  equals (x,y) {+  equals (x, y) {     return x `ReadAtH:equals` y   } }
+ lib/container/test/testing.0rt view
@@ -0,0 +1,257 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "CheckSet equality success" {+  success TestChecker+}++unittest equals {+  SortedSet<Int> actual <- SortedSet<Int>.new().append(1).append(2).append(3)+  SortedSet<Int> expected <- SortedSet<Int>.new().append(1).append(2).append(3)+  \ actual `Matches:with` CheckSet:equals(expected)+}+++testcase "CheckSet:equals different" {+  failure TestChecker+  require "\"10\""+  require "\"20\""+  require "\"30\""+  require "\"40\""+  require "\"50\""+  require "\"60\""+}++unittest test {+  SortedSet<Int> actual <- SortedSet<Int>.new().append(10).append(20).append(30)+  SortedSet<Int> expected <- SortedSet<Int>.new().append(40).append(50).append(60)+  \ actual `Matches:with` CheckSet:equals(expected)+}+++testcase "CheckSet:equals extra" {+  failure TestChecker+  require "\"40\""+  exclude "\"10\""+  exclude "\"20\""+  exclude "\"30\""+}++unittest test {+  SortedSet<Int> actual <- SortedSet<Int>.new().append(10).append(20).append(30).append(40)+  SortedSet<Int> expected <- SortedSet<Int>.new().append(10).append(20).append(30)+  \ actual `Matches:with` CheckSet:equals(expected)+}+++testcase "CheckSet:equals missing" {+  failure TestChecker+  require "\"40\""+  exclude "\"10\""+  exclude "\"20\""+  exclude "\"30\""+}++unittest test {+  SortedSet<Int> actual <- SortedSet<Int>.new().append(10).append(20).append(30)+  SortedSet<Int> expected <- SortedSet<Int>.new().append(10).append(20).append(30).append(40)+  \ actual `Matches:with` CheckSet:equals(expected)+}+++testcase "CheckMap equality success" {+  success TestChecker+}++unittest equals {+  SortedMap<String, Int> actual <- SortedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2)+      .set("three", 3)+  HashedMap<String, Int> expected <- HashedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2)+      .set("three", 3)+  \ actual `Matches:with` CheckMap:equals(expected)+}+++testcase "CheckMap:equals different" {+  failure TestChecker+  require "two"+  require "2900.+2"+  require "three"+  require "3.+3900"+}++unittest test {+  SortedMap<String, Int> actual <- SortedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2900)+      .set("three", 3)+  HashedMap<String, Int> expected <- HashedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2)+      .set("three", 3900)+  \ actual `Matches:with` CheckMap:equals(expected)+}+++testcase "CheckMap:equals extra" {+  failure TestChecker+  require "zero"+}++unittest test {+  SortedMap<String, Int> actual <- SortedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2)+      .set("three", 3)+  HashedMap<String, Int> expected <- HashedMap<String, Int>.new()+      .set("zero", 0)+      .set("one", 1)+      .set("two", 2)+      .set("three", 3)+  \ actual `Matches:with` CheckMap:equals(expected)+}+++testcase "CheckMap:equals missing" {+  failure TestChecker+  require "four"+}++unittest test {+  SortedMap<String, Int> actual <- SortedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2)+      .set("three", 3)+      .set("four", 4)+  HashedMap<String, Int> expected <- HashedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2)+      .set("three", 3)+  \ actual `Matches:with` CheckMap:equals(expected)+}+++testcase "CheckMap equality success" {+  success TestChecker+}++unittest matches {+  SortedMap<String, Int> actual <- SortedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2)+      .set("three", 3)+  HashedMap<String, ValueMatcher<Int>> expected <- HashedMap<String, ValueMatcher<Int>>.new()+      .set("one", CheckValue:equals(1))+      .set("two", CheckValue:equals(2))+      .set("three", CheckValue:equals(3))+  \ actual `Matches:with` CheckMap:matches(expected)+}+++testcase "CheckMap:matches different" {+  failure TestChecker+  require "two"+  require "2900.+2"+  require "three"+  require "3.+3900"+}++unittest test {+  SortedMap<String, Int> actual <- SortedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2900)+      .set("three", 3)+  HashedMap<String, ValueMatcher<Int>> expected <- HashedMap<String, ValueMatcher<Int>>.new()+      .set("one", CheckValue:equals(1))+      .set("two", CheckValue:equals(2))+      .set("three", CheckValue:equals(3900))+  \ actual `Matches:with` CheckMap:matches(expected)+}+++testcase "CheckMap:matches extra" {+  failure TestChecker+  require "zero"+}++unittest test {+  SortedMap<String, Int> actual <- SortedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2)+      .set("three", 3)+  HashedMap<String, ValueMatcher<Int>> expected <- HashedMap<String, ValueMatcher<Int>>.new()+      .set("zero", CheckValue:equals(0))+      .set("one", CheckValue:equals(1))+      .set("two", CheckValue:equals(2))+      .set("three", CheckValue:equals(3))+  \ actual `Matches:with` CheckMap:matches(expected)+}+++testcase "CheckMap:matches missing" {+  failure TestChecker+  require "four"+}++unittest test {+  SortedMap<String, Int> actual <- SortedMap<String, Int>.new()+      .set("one", 1)+      .set("two", 2)+      .set("three", 3)+      .set("four", 4)+  HashedMap<String, ValueMatcher<Int>> expected <- HashedMap<String, ValueMatcher<Int>>.new()+      .set("one", CheckValue:equals(1))+      .set("two", CheckValue:equals(2))+      .set("three", CheckValue:equals(3))+  \ actual `Matches:with` CheckMap:matches(expected)+}+++testcase "CheckMap:using success" {+  success TestChecker+}++unittest test {+  SortedMap<String, TestValue> actual <- SortedMap<String, TestValue>.new()+      .set("one", TestValue.new("one"))+      .set("two", TestValue.new("two"))+  SortedMap<String, TestValue> expected <- SortedMap<String, TestValue>.new()+      .set("one", TestValue.new("one"))+      .set("two", TestValue.new("two"))+  \ actual `Matches:with` CheckMap:matches(CheckMap:using(expected))+}+++testcase "CheckMap:using failure" {+  failure TestChecker+  require "TWO.+two"+}++unittest test {+  SortedMap<String, TestValue> actual <- SortedMap<String, TestValue>.new()+      .set("one", TestValue.new("one"))+      .set("two", TestValue.new("TWO"))+  SortedMap<String, TestValue> expected <- SortedMap<String, TestValue>.new()+      .set("one", TestValue.new("one"))+      .set("two", TestValue.new("two"))+  \ actual `Matches:with` CheckMap:matches(CheckMap:using(expected))+}
lib/container/test/type-map.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -17,7 +17,7 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "TypeMap tests" {-  success+  success TestChecker }  unittest basicOperations {@@ -27,21 +27,21 @@   TypeKey<String> keyString <- TypeKey<String>.new()   TypeKey<Value>  keyValue  <- TypeKey<Value>.new() -  \ Testing.checkOptional(map.get(keyInt),   empty)-  \ Testing.checkOptional(map.get(keyString),empty)-  \ Testing.checkOptional(map.get(keyValue), empty)+  \ map.get(keyInt)    `Matches:with` CheckValue:equals(empty?Int)+  \ map.get(keyString) `Matches:with` CheckValue:equals(empty?String)+  \ map.get(keyValue)  `Matches:with` CheckValue:equals(empty?Value) -  \ map.set(keyInt,1)-  \ map.set(keyString,"a")-  \ map.set(keyValue,Value.new())+  \ map.set(keyInt, 1)+  \ map.set(keyString, "a")+  \ map.set(keyValue, Value.new()) -  \ Testing.checkOptional(map.get(keyInt),   1)-  \ Testing.checkOptional(map.get(keyString),"a")-  \ Testing.checkOptional(map.get(keyValue), Value.new())+  \ map.get(keyInt) `Matches:with` CheckValue:equals(   1)+  \ map.get(keyString) `Matches:with` CheckValue:equals("a")+  \ map.get(keyValue) `Matches:with` CheckValue:equals( Value.new())    \ map.remove(keyString) -  \ Testing.checkOptional(map.get(keyString),empty)+  \ map.get(keyString) `Matches:with` CheckValue:equals(empty?String) }  unittest wrongReturnType {@@ -50,56 +50,57 @@   TypeKey<String> keyString <- TypeKey<String>.new()    // Added as Formatted, which means it cannot be retrieved as String later.-  \ map.set<Formatted>(keyString,"a")-  \ Testing.checkOptional(map.get<String>(keyString),empty)+  \ map.set<Formatted>(keyString, "a")+  \ map.get<String>(keyString) `Matches:with` CheckValue:equals(empty?String) -  \ map.set<String>(keyString,"a")-  \ Testing.checkOptional(map.get<String>(keyString),"a")+  \ map.set<String>(keyString, "a")+  \ map.get<String>(keyString) `Matches:with` CheckValue:equals("a") }  unittest duplicate {   TypeKey<Int>    keyInt    <- TypeKey<Int>.new()   TypeKey<String> keyString <- TypeKey<String>.new() -  TypeMap map <- TypeMap.new().set(keyInt,1).set(keyString,"a")+  TypeMap map <- TypeMap.new().set(keyInt, 1).set(keyString, "a")    TypeMap copy <- map.duplicate()-  \ Testing.checkOptional(copy.get(keyInt),1)-  \ Testing.checkOptional(copy.get(keyString),"a")+  \ copy.get(keyInt) `Matches:with` CheckValue:equals(1)+  \ copy.get(keyString) `Matches:with` CheckValue:equals("a")    \ copy.remove(keyString)-  \ Testing.checkOptional(copy.get(keyInt),1)-  \ Testing.checkOptional(copy.get(keyString),empty)-  \ Testing.checkOptional(map.get(keyString),"a")+  \ copy.get(keyInt)    `Matches:with` CheckValue:equals(1)+  \ copy.get(keyString) `Matches:with` CheckValue:equals(empty?String)+  \ map.get(keyString)  `Matches:with` CheckValue:equals("a") }  unittest getValues {   TypeMap map <- TypeMap.new()-      .set(TypeKey<String>.new(),"one")-      .set(TypeKey<Int>.new(),2)-      .set(TypeKey<String>.new(),"two")-      .set(TypeKey<Int>.new(),1)+      .set(TypeKey<String>.new(), "one")+      .set(TypeKey<Int>.new(), 2)+      .set(TypeKey<String>.new(), "two")+      .set(TypeKey<Int>.new(), 1) -  [Container&SetReader<String>] actual <- map.getAll(SortedSet<String>.new())+  [Container & SetReader<String>] actual <- map.getAll(SortedSet<String>.new()) -  \ Testing.checkEquals(actual.size(),2)-  \ Testing.checkTrue(actual.member("one"))-  \ Testing.checkTrue(actual.member("two"))+  \ actual.size() `Matches:with` CheckValue:equals(2)+  \ actual.member("one") `Matches:with` CheckValue:equals(true)+  \ actual.member("two") `Matches:with` CheckValue:equals(true) }  unittest keyEquals {   TypeKey<Int>    key1 <- TypeKey<Int>.new()   TypeKey<Int>    key2 <- TypeKey<Int>.new()   TypeKey<String> key3 <- TypeKey<String>.new()-  \ Testing.checkEquals<TypeKey<Int>>(key1,key1)-  \ Testing.checkFalse(key1 `TypeKey<any>.equals` key2)-  \ Testing.checkFalse(key1 `TypeKey<any>.equals` key3)+  \ key1 `Matches:with` CheckValue:equals(key1)+  \ (key1 `TypeKey<any>.equals` key2) `Matches:with` CheckValue:equals(false)+  \ (key1 `TypeKey<any>.equals` key2) `Matches:with` CheckValue:equals(false)+  \ (key1 `TypeKey<any>.equals` key3) `Matches:with` CheckValue:equals(false) }  unittest keyHashed {   TypeKey<Int> key1 <- TypeKey<Int>.new()   TypeKey<Int> key2 <- TypeKey<Int>.new()-  \ Testing.checkNotEquals(key1.hashed(),key2.hashed())+  \ key1.hashed() `Matches:with` CheckValue:notEquals(key2.hashed()) }  concrete Value {@@ -118,15 +119,15 @@     return "Value"   } -  equals (_,_) {+  equals (_, _) {     return true   } }   testcase "TypeKey formatted" {-  crash-  require "TypeKey<Int>\{[0-9]+\}"+  failure+  require "TypeKey<Int>\{[0-9a-fA-F]+\}" }  unittest test {
lib/container/test/vector.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,17 +17,17 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "Vector tests" {-  success+  success TestChecker }  unittest createSize {   Vector<Int> values <- Vector:createSize<Int>(10)-  \ Testing.checkEquals(values.size(),10)+  \ values.size() `Matches:with` CheckValue:equals(10)    scoped {     Int i <- 0   } in while (i < values.size()) {-    \ Testing.checkEquals(values.readAt(i),Int.default())+    \ values.readAt(i) `Matches:with` CheckValue:equals(Int.default())   } update {     i <- i+1   }@@ -40,16 +40,16 @@     Int i <- 0   } in while (i < 10) {     \ values.append(i)-    \ Testing.checkEquals(values.size(),i+1)+    \ values.size() `Matches:with` CheckValue:equals(i+1)   } update {     i <- i+1   }-  \ Testing.checkEquals(values.size(),10)+  \ values.size() `Matches:with` CheckValue:equals(10)    scoped {     Int i <- 0   } in while (i < values.size()) {-    \ Testing.checkEquals(values.readAt(i),i)+    \ values.readAt(i) `Matches:with` CheckValue:equals(i)   } update {     i <- i+1   }@@ -62,21 +62,21 @@     Int i <- 0   } in while (i < 10) {     \ values.push(i)-    \ Testing.checkEquals(values.size(),i+1)+    \ values.size() `Matches:with` CheckValue:equals(i+1)   } update {     i <- i+1   }-  \ Testing.checkEquals(values.size(),10)+  \ values.size() `Matches:with` CheckValue:equals(10)    scoped {     Int i <- 0   } in while (i < 10) {-    \ Testing.checkEquals(values.pop(),10-i-1)-    \ Testing.checkEquals(values.size(),10-i-1)+    \ values.pop() `Matches:with` CheckValue:equals(10-i-1)+    \ values.size() `Matches:with` CheckValue:equals(10-i-1)   } update {     i <- i+1   }-  \ Testing.checkEquals(values.size(),0)+  \ values.size() `Matches:with` CheckValue:equals(0) }  unittest writeAt {@@ -85,7 +85,7 @@   scoped {     Int i <- 0   } in while (i < values.size()) {-    \ values.writeAt(i,2*i)+    \ values.writeAt(i, 2*i)   } update {     i <- i+1   }@@ -93,7 +93,7 @@   scoped {     Int i <- 0   } in while (i < values.size()) {-    \ Testing.checkEquals(values.readAt(i),2*i)+    \ values.readAt(i) `Matches:with` CheckValue:equals(2*i)   } update {     i <- i+1   }@@ -110,26 +110,26 @@   \ vector.push(1)    traverse (vector.defaultOrder() -> Int i) {-    \ Testing.checkEquals(i,vector.readAt(index))+    \ i `Matches:with` CheckValue:equals(vector.readAt(index))     index <- index+1   } -  \ Testing.checkEquals(index,6)+  \ index `Matches:with` CheckValue:equals(6) }  unittest duplicate {   Vector<Int> vector <- Vector<Int>.default().push(1).push(2)    Vector<Int> copy <- vector.duplicate()-  \ Testing.checkEquals(copy.size(),2)-  \ Testing.checkEquals(copy.readAt(0),1)-  \ Testing.checkEquals(copy.readAt(1),2)+  \ copy.size() `Matches:with` CheckValue:equals(2)+  \ copy.readAt(0) `Matches:with` CheckValue:equals(1)+  \ copy.readAt(1) `Matches:with` CheckValue:equals(2) -  \ copy.writeAt(1,3)+  \ copy.writeAt(1, 3)   \ copy.pop()-  \ Testing.checkEquals(copy.size(),1)-  \ Testing.checkEquals(copy.readAt(0),1)-  \ Testing.checkEquals(vector.readAt(1),2)+  \ copy.size() `Matches:with` CheckValue:equals(1)+  \ copy.readAt(0) `Matches:with` CheckValue:equals(1)+  \ vector.readAt(1) `Matches:with` CheckValue:equals(2) }  concrete Value {@@ -151,20 +151,20 @@   testcase "distinct default values in pre-sized Vector" {-  success+  success TestChecker }  unittest test {   Vector<Type> values <- Vector:createSize<Type>(10)   \ values.readAt(3).set(7) -  \ Testing.checkEquals(values.readAt(3),Type.create(7))+  \ values.readAt(3) `Matches:with` CheckValue:equals(Type.create(7))    scoped {     Int i <- 0   } in while (i < values.size()) {     if (i != 3) {-      \ Testing.checkEquals(values.readAt(i),Type.create(0))+      \ values.readAt(i) `Matches:with` CheckValue:equals(Type.create(0))     }   } update {     i <- i+1@@ -195,7 +195,7 @@     return value.formatted()   } -  equals (x,y) {+  equals (x, y) {     return x.get() == y.get()   } @@ -211,7 +211,7 @@   testcase "negative Vector index" {-  crash+  failure }  unittest test {@@ -221,7 +221,7 @@   testcase "Vector index out of bounds" {-  crash+  failure }  unittest test {
+ lib/container/testing.0rp view
@@ -0,0 +1,39 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++concrete CheckSet {+  @category equals<#k>+    #k requires Formatted+  ([SetReader<#k> & DefaultOrder<#k>]) -> (ValueMatcher<[SetReader<#k> & DefaultOrder<#k>]>)+}++concrete CheckMap {+  @category using<#k, #v>+    #v requires TestCompare<#v>+  ([SetReader<#k> & DefaultOrder<KeyValue<#k, #v>>]) -> ([SetReader<#k> & DefaultOrder<KeyValue<#k, ValueMatcher<#v>>>])++  @category equals<#k, #v>+    #k requires Formatted+    #v requires Formatted+    #v defines Equals<#v>+  ([SetReader<#k> & DefaultOrder<KeyValue<#k, #v>>]) -> (ValueMatcher<[KVReader<#k, #v> & KeyOrder<#k>]>)++  @category matches<#k, #v>+    #k requires Formatted+  ([SetReader<#k> & DefaultOrder<KeyValue<#k, ValueMatcher<#v>>>]) -> (ValueMatcher<[KVReader<#k, #v> & KeyOrder<#k>]>)+}
lib/container/type-map.0rp view
@@ -28,7 +28,7 @@   //   // Params:   // - #x: The value type being stored.-  @value set<#x> (TypeKey<#x>,#x) -> (TypeMap)+  @value set<#x> (TypeKey<#x>, #x) -> (TypeMap)    // Remove the value associated with the key if present and return self.   @value remove (TypeKey<any>) -> (TypeMap)@@ -47,7 +47,7 @@   @value get<#x> (TypeKey<#x>) -> (optional #x)    // Get all values of type #x.-  @value getAll<#c,#x>+  @value getAll<#c, #x>     #c requires Append<#x>   (#c) -> (#c) }
lib/file/.zeolite-module view
@@ -20,4 +20,4 @@     categories: [RawFileWriter]   } ]-mode: incremental {}+mode: incremental { }
lib/file/test/tests.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2020 Kevin P. Barry+Copyright 2020,2023 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.@@ -17,7 +17,7 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "read and write" {-  success+  success TestChecker }  unittest readWrite {@@ -28,12 +28,12 @@   } cleanup {     \ writer.freeResource()   } in {-    \ Testing.checkEmpty(writer.getFileError())+    \ present(writer.getFileError()) `Matches:with` CheckValue:equals(false)     Int writeSize <- writer.writeBlock(data)     if (writeSize != data.size()) {       fail(writeSize)     }-    \ Testing.checkEmpty(writer.getFileError())+    \ present(writer.getFileError()) `Matches:with` CheckValue:equals(false)   }    scoped {@@ -41,7 +41,7 @@   } cleanup {     \ reader.freeResource()   } in {-    \ Testing.checkEmpty(reader.getFileError())+    \ present(reader.getFileError()) `Matches:with` CheckValue:equals(false)      scoped {       String data2 <- reader.readBlock(8)@@ -53,7 +53,7 @@     } in if (data2 != "some\x00data") {       fail("\"" + data2 + "\"")     }-    \ Testing.checkEmpty(reader.getFileError())+    \ present(reader.getFileError()) `Matches:with` CheckValue:equals(false)      if (!reader.pastEnd()) {       fail("more data in file")@@ -70,7 +70,7 @@     \ writer.freeResource()   } in \ writer.writeBlock(data) -  \ Testing.checkEquals(FileTesting.forceReadFile("testfile"),data)+  \ FileTesting.forceReadFile("testfile") `Matches:with` CheckValue:equals(data) }  unittest readEmpty {@@ -81,7 +81,7 @@   if (data != "") {     fail("\"" + data + "\"")   }-  \ Testing.checkEmpty(reader.getFileError())+  \ present(reader.getFileError()) `Matches:with` CheckValue:equals(false)   if (!reader.pastEnd()) {     fail("more data in file")   }@@ -89,18 +89,18 @@  unittest readMissing {   RawFileReader reader <- RawFileReader.open("do-not-create-this-file")-  \ Testing.checkPresent(reader.getFileError())+  \ present(reader.getFileError()) `Matches:with` CheckValue:equals(true) }  unittest unwritable {   RawFileWriter writer <- RawFileWriter.open("testfile")   \ writer.freeResource()-  \ Testing.checkPresent(writer.getFileError())+  \ present(writer.getFileError()) `Matches:with` CheckValue:equals(true) }   testcase "read missing file crash" {-  crash+  failure   require "do-not-create-this-file"   require "RawFileReader .*creation" }@@ -112,7 +112,7 @@   testcase "unwritable file crash" {-  crash+  failure   require "testfile"   require "RawFileWriter .*creation" }
lib/math/.zeolite-module view
@@ -29,4 +29,4 @@     categories: [RandomUniform]   } ]-mode: incremental {}+mode: incremental { }
lib/math/categorical-tree.0rp view
@@ -33,11 +33,11 @@   // Return the value at the given offset.   //   // Notes:-  // - The offset must be within [0,getTotal()). A uniform selection in that+  // - The offset must be within [0, getTotal()). A uniform selection in that   //   range will provide samples that follow the categorical distribution   //   corresponding to the relative weights of the respective #c.   // - The return value is deterministic. If you were to iterate over-  //   [0,getTotal()), you'd get an increasing sequence of all #c in the+  //   [0, getTotal()), you'd get an increasing sequence of all #c in the   //   CategoricalReader, each repeated the number of times indicated by its   //   respective weight.   // - Also see RandomCategorical in random.0rp.@@ -74,7 +74,7 @@   // Notes:   // - The weight must not be negative.   // - The sum of all weights (see getTotal()) must not exceed Int.maxBound().-  @value setWeight (#c,Int) -> (#self)+  @value setWeight (#c, Int) -> (#self)    // Increments the weight of the value by 1.   @value incrWeight (#c) -> (#self)
lib/math/math.0rp view
@@ -36,12 +36,12 @@   @type log (Float) -> (Float)   @type log10 (Float) -> (Float)   @type log2 (Float) -> (Float)-  @type pow (Float,Float) -> (Float)+  @type pow (Float, Float) -> (Float)   @type sqrt (Float) -> (Float)    @type ceil (Float) -> (Float)   @type floor (Float) -> (Float)-  @type fmod (Float,Float) -> (Float)+  @type fmod (Float, Float) -> (Float)   @type trunc (Float) -> (Float)   @type round (Float) -> (Float)   @type fabs (Float) -> (Float)
lib/math/random.0rp view
@@ -37,7 +37,7 @@   refines Generator<Float>    // Creates a new generator with the specified mean and standard deviation.-  @type new (Float,Float) -> (#self)+  @type new (Float, Float) -> (#self)    // Resets the seed for RNG.   @value setSeed (Int) -> (#self)@@ -48,9 +48,9 @@   refines Generator<Float>    // Creates a new generator with the specified min and max values.-  @type new (Float,Float) -> (#self)+  @type new (Float, Float) -> (#self) -  // Creates a new generator for the range [0.0,1.0).+  // Creates a new generator for the range [0.0, 1.0).   @type probability () -> (#self)    // Resets the seed for RNG.@@ -72,10 +72,10 @@   // Creates a generator for the provided distribution.   //   // Notes:-  // - The Generator<Float> *must* return values in the range [0,1).+  // - The Generator<Float> *must* return values in the range [0, 1).   // - The distribution is not copied; therefore, changes to the distribution   //   will affect the returned generator.-  @category sampleWith<#c> (CategoricalReader<#c>,Generator<Float>) -> (RandomCategorical<#c>)+  @category sampleWith<#c> (CategoricalReader<#c>, Generator<Float>) -> (RandomCategorical<#c>)    // Returns true if the distribution is empty.   //@@ -93,9 +93,9 @@   // 2. Samples from the copy *without* replacement until the tree is empty.   //   // Notes:-  // - The Generator must only return values in [0,1).+  // - The Generator must only return values in [0, 1).   // - If category c has a weight of n, it will occur n times in the output.-  @category permuteFrom<#c> (CategoricalTree<#c>,Generator<Float>,Append<#c>) -> ()+  @category permuteFrom<#c> (CategoricalTree<#c>, Generator<Float>, Append<#c>) -> ()    // Creates a permutation from the CategoricalTree.   //@@ -103,8 +103,8 @@   // 2. Samples from the copy *without* replacement until the tree is empty.   //   // Notes:-  // - The Generator must only return values in [0,1).+  // - The Generator must only return values in [0, 1).   // - If category c has a weight of n, it will occur *once* in the output, but   //   it will have a relative chance of n to be chosen ahead of others.-  @category permuteFromWeight<#c> (CategoricalTree<#c>,Generator<Float>,Append<#c>) -> ()+  @category permuteFromWeight<#c> (CategoricalTree<#c>, Generator<Float>, Append<#c>) -> () }
lib/math/src/categorical-tree.0rx view
@@ -17,14 +17,14 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define CategoricalTree {-  @value AutoBinaryTree<CategoricalTreeNode<#c>,#c,Int,CategoricalSearch<#c>> tree+  @value AutoBinaryTree<CategoricalTreeNode<#c>, #c, Int, CategoricalSearch<#c>> tree    default () {     return new()   }    new () {-    return #self{ AutoBinaryTree<CategoricalTreeNode<#c>,#c,Int,CategoricalSearch<#c>>.new() }+    return #self{ AutoBinaryTree<CategoricalTreeNode<#c>, #c, Int, CategoricalSearch<#c>>.new() }   }    duplicate () {@@ -35,13 +35,13 @@     return CategoricalTreeNode<#c>.tryTotal(tree.getRoot())   } -  setWeight (cat,size) {+  setWeight (cat, size) {     if (size < 0) {       fail("size must not be negative")     } elif (size > 0) {-      \ tree.swap(cat,size)+      \ tree.swap(cat, size)     } else {-      \ tree.swap(cat,empty)+      \ tree.swap(cat, empty)     }     return self   }@@ -57,12 +57,12 @@   }    incrWeight (cat) {-    \ setWeight(cat,getWeight(cat)+1)+    \ setWeight(cat, getWeight(cat)+1)     return self   }    decrWeight (cat) {-    \ setWeight(cat,getWeight(cat)-1)+    \ setWeight(cat, getWeight(cat)-1)     return self   } @@ -72,7 +72,7 @@     } elif (pos >= getTotal()) {       fail("position must be strictly less than the total")     } else {-      return require(CategoricalTreeNode<#c>.findPosition(pos,tree.getRoot()))+      return require(CategoricalTreeNode<#c>.findPosition(pos, tree.getRoot()))     }   } @@ -86,23 +86,23 @@ }  define ValidatedTree {-  @value AutoBinaryTree<CategoricalTreeNode<#c>,#c,Int,CategoricalSearch<#c>> tree+  @value AutoBinaryTree<CategoricalTreeNode<#c>, #c, Int, CategoricalSearch<#c>> tree    new () { $NoTrace$-    return #self{ AutoBinaryTree<CategoricalTreeNode<#c>,#c,Int,CategoricalSearch<#c>>.new() }+    return #self{ AutoBinaryTree<CategoricalTreeNode<#c>, #c, Int, CategoricalSearch<#c>>.new() }   }    getTotal () { $NoTrace$     return CategoricalTreeNode<#c>.tryTotal(tree.getRoot())   } -  setWeight (cat,size) { $NoTrace$+  setWeight (cat, size) { $NoTrace$     if (size < 0) {       fail("size must not be negative")     } elif (size > 0) {-      \ tree.swap(cat,size)+      \ tree.swap(cat, size)     } else {-      \ tree.swap(cat,empty)+      \ tree.swap(cat, empty)     }     \ validateTotal(tree.getRoot())     return self@@ -124,7 +124,7 @@     } elif (pos >= getTotal()) {       fail("position must be strictly less than the total")     } else {-      return require(CategoricalTreeNode<#c>.findPosition(pos,tree.getRoot()))+      return require(CategoricalTreeNode<#c>.findPosition(pos, tree.getRoot()))     }   } @@ -154,18 +154,18 @@ }  @value interface CategoricalSearch<|#c> {-  refines BinaryTreeNode<#c,Int>+  refines BinaryTreeNode<#c, Int>    getTotal () -> (Int) }  concrete CategoricalTreeNode<#c> {-  defines KVFactory<#c,Int>+  defines KVFactory<#c, Int>   refines CategoricalSearch<#c>-  refines BalancedTreeNode<CategoricalTreeNode<#c>,#c,Int>+  refines BalancedTreeNode<CategoricalTreeNode<#c>, #c, Int>   refines Duplicate -  @type findPosition (Int,optional CategoricalSearch<#c>) -> (optional #c)+  @type findPosition (Int, optional CategoricalSearch<#c>) -> (optional #c)   @type tryTotal (optional CategoricalSearch<#c>) -> (Int)    @value getTotal () -> (Int)@@ -193,7 +193,7 @@     return #self{ height, key, size, total, lower2, higher2 }   } -  findPosition (pos,node) (cat) {+  findPosition (pos, node) (cat) {     cat <- empty     if (present(node)) {       scoped {@@ -202,11 +202,11 @@         CategoricalSearch<#c> node2 <- require(node)         Int lower <- tryTotal(node2.getLower())         Int size <- node2.getValue()-        $ReadOnly[node2,lower,size]$+        $ReadOnly[node2, lower, size]$       } in if (pos2 < node2.getTotal()) {         if (pos2 < lower) {           // pos2 is in the 1st (lower) of the 3 sections.-          return findPosition(pos2,node2.getLower())+          return findPosition(pos2, node2.getLower())         }         pos2 <- pos2-lower         if (pos2 < size) {@@ -215,7 +215,7 @@         }         pos2 <- pos2-size           // pos2 is in the 3rd (higher) of the 3 sections.-        return findPosition(pos2,node2.getHigher())+        return findPosition(pos2, node2.getHigher())       }     }   }@@ -228,7 +228,7 @@     }   } -  newNode (k,v) {+  newNode (k, v) {     return #self{ 1, k, v, v, empty, empty }   } 
lib/math/src/random.0rx view
@@ -17,10 +17,10 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define Randomize {-  permuteFrom (tree,random,output) {+  permuteFrom (tree, random, output) {     CategoricalTree<#c> copy <- tree.duplicate()     Generator<#c> generator <- copy `RandomCategorical:sampleWith` random-    $Hidden[tree,random]$+    $Hidden[tree, random]$     while (copy.getTotal() > 0) {       #c cat <- generator.generate()       \ output.append(cat)@@ -28,14 +28,14 @@     }   } -  permuteFromWeight (tree,random,output) {+  permuteFromWeight (tree, random, output) {     CategoricalTree<#c> copy <- tree.duplicate()     Generator<#c> generator <- copy `RandomCategorical:sampleWith` random-    $Hidden[tree,random]$+    $Hidden[tree, random]$     while (copy.getTotal() > 0) {       #c cat <- generator.generate()       \ output.append(cat)-      \ copy.setWeight(cat,0)+      \ copy.setWeight(cat, 0)     }   } }@@ -46,7 +46,7 @@   @value Float constant    new (constant) {-    return GenerateConstant{ constant }+    return delegate -> #self   }    generate () {@@ -60,8 +60,8 @@   @value CategoricalReader<#c> categorical   @value Generator<Float> random -  sampleWith (categorical,random) {-    return RandomCategorical<#c>{ categorical, random }+  sampleWith (categorical, random) {+    return delegate -> RandomCategorical<#c>   }    generate () {
lib/math/src/token.0rx view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,14 +17,12 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define Token {-  $ReadOnlyExcept[counter]$+  $ReadOnlyExcept[]$    @category Mutex mutex <- SpinlockMutex.new()-  @category HashedMap<String,Token> toToken <- HashedMap<String,Token>.new()-  @category Int counter <- 0+  @category HashedMap<String, Token> toToken <- HashedMap<String, Token>.new()    @value String string-  @value Int    value    from (string) (token) {     scoped {@@ -32,10 +30,10 @@       optional Token existing <- toToken.get(string)     } cleanup {       \ mutex.unlock()-    } in if (present(existing)) {-      return require(existing)+    } in if (`present` existing) {+      token <- `require` existing     } else {-      \ toToken.set(string,(token <- Token{ string, (counter <- counter+1) }))+      \ string `toToken.set` (token <- Token{ string })     }   } @@ -44,17 +42,14 @@   }    hashed () {-    return value.hashed()+    return identify(self).hashed()   } -  equals (x,y) {-    return x.get() == y.get()+  equals (x, y) {+    return identify(x) == identify(y)   } -  lessThan (x,y) {-    return x.get() < y.get()+  lessThan (x, y) {+    return identify(x) < identify(y)   }--  @value get () -> (Int)-  get () { return value } }
lib/math/src/validated-tree.0rp view
@@ -31,7 +31,7 @@   @type new () -> (#self)    @value getTotal  ()       -> (Int)-  @value setWeight (#c,Int) -> (#self)+  @value setWeight (#c, Int) -> (#self)   @value getWeight (#c)     -> (Int)   @value locate    (Int)    -> (#c) }
lib/math/test/categorical-tree.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,17 +17,17 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "CategoricalTree tests" {-  success+  success TestChecker }  unittest simpleInsertion {   CategoricalTree<Int> tree <- CategoricalTree<Int>.default()-      .setWeight(1,3)-      .setWeight(6,2)-      .setWeight(3,1)-      .setWeight(5,4)-      .setWeight(4,3)-      .setWeight(2,7)+      .setWeight(1, 3)+      .setWeight(6, 2)+      .setWeight(3, 1)+      .setWeight(5, 4)+      .setWeight(4, 3)+      .setWeight(2, 7)    Vector<Int> expected <- Vector<Int>.new()       .push(1).push(1).push(1)@@ -37,31 +37,31 @@       .push(5).push(5).push(5).push(5)       .push(6).push(6) -  \ Testing.checkEquals(tree.getTotal(),expected.size())-  \ Testing.checkEquals(tree.getWeight(1),3)-  \ Testing.checkEquals(tree.getWeight(2),7)-  \ Testing.checkEquals(tree.getWeight(3),1)-  \ Testing.checkEquals(tree.getWeight(4),3)-  \ Testing.checkEquals(tree.getWeight(5),4)-  \ Testing.checkEquals(tree.getWeight(6),2)+  \ tree.getTotal() `Matches:with` CheckValue:equals(expected.size())+  \ tree.getWeight(1) `Matches:with` CheckValue:equals(3)+  \ tree.getWeight(2) `Matches:with` CheckValue:equals(7)+  \ tree.getWeight(3) `Matches:with` CheckValue:equals(1)+  \ tree.getWeight(4) `Matches:with` CheckValue:equals(3)+  \ tree.getWeight(5) `Matches:with` CheckValue:equals(4)+  \ tree.getWeight(6) `Matches:with` CheckValue:equals(2)    traverse (Counter.zeroIndexed(tree.getTotal()) -> Int pos) {-    \ Testing.checkEquals(tree.locate(pos),expected.readAt(pos))+    \ tree.locate(pos) `Matches:with` CheckValue:equals(expected.readAt(pos))   } }  unittest modifySizes {   CategoricalTree<Int> tree <- CategoricalTree<Int>.new()-      .setWeight(1,3)-      .setWeight(6,2)-      .setWeight(3,1)-      .setWeight(5,4)-      .setWeight(4,3)-      .setWeight(2,7)-      .setWeight(7,3)+      .setWeight(1, 3)+      .setWeight(6, 2)+      .setWeight(3, 1)+      .setWeight(5, 4)+      .setWeight(4, 3)+      .setWeight(2, 7)+      .setWeight(7, 3)       // modifications start here-      .setWeight(5,1)-      .setWeight(3,0)+      .setWeight(5, 1)+      .setWeight(3, 0)    Vector<Int> expected <- Vector<Int>.new()       .push(1).push(1).push(1)@@ -71,22 +71,22 @@       .push(6).push(6)       .push(7).push(7).push(7) -  \ Testing.checkEquals(tree.getTotal(),expected.size())-  \ Testing.checkEquals(tree.getWeight(1),3)-  \ Testing.checkEquals(tree.getWeight(2),7)-  \ Testing.checkEquals(tree.getWeight(3),0)-  \ Testing.checkEquals(tree.getWeight(4),3)-  \ Testing.checkEquals(tree.getWeight(5),1)-  \ Testing.checkEquals(tree.getWeight(6),2)-  \ Testing.checkEquals(tree.getWeight(7),3)+  \ tree.getTotal() `Matches:with` CheckValue:equals(expected.size())+  \ tree.getWeight(1) `Matches:with` CheckValue:equals(3)+  \ tree.getWeight(2) `Matches:with` CheckValue:equals(7)+  \ tree.getWeight(3) `Matches:with` CheckValue:equals(0)+  \ tree.getWeight(4) `Matches:with` CheckValue:equals(3)+  \ tree.getWeight(5) `Matches:with` CheckValue:equals(1)+  \ tree.getWeight(6) `Matches:with` CheckValue:equals(2)+  \ tree.getWeight(7) `Matches:with` CheckValue:equals(3)    traverse (Counter.zeroIndexed(tree.getTotal()) -> Int pos) {-    \ Testing.checkEquals(tree.locate(pos),expected.readAt(pos))+    \ tree.locate(pos) `Matches:with` CheckValue:equals(expected.readAt(pos))   }    // Use ReadAt aliases for the same functionality.   traverse (Counter.zeroIndexed(tree.size()) -> Int pos) {-    \ Testing.checkEquals(tree.readAt(pos),expected.readAt(pos))+    \ tree.readAt(pos) `Matches:with` CheckValue:equals(expected.readAt(pos))   } } @@ -96,59 +96,59 @@     .incrWeight(1)     .incrWeight(1) -  \ Testing.checkEquals(tree.getTotal(),3)-  \ Testing.checkEquals(tree.getWeight(1),3)+  \ tree.getTotal() `Matches:with` CheckValue:equals(3)+  \ tree.getWeight(1) `Matches:with` CheckValue:equals(3) }  unittest decrement {   CategoricalTree<Int> tree <- CategoricalTree<Int>.new()-    .setWeight(1,10)+    .setWeight(1, 10)     .decrWeight(1)     .decrWeight(1)     .decrWeight(1) -  \ Testing.checkEquals(tree.getTotal(),7)-  \ Testing.checkEquals(tree.getWeight(1),7)+  \ tree.getTotal() `Matches:with` CheckValue:equals(7)+  \ tree.getWeight(1) `Matches:with` CheckValue:equals(7) }  unittest duplicate {-  CategoricalTree<Int> tree <- CategoricalTree<Int>.new().setWeight(1,1).setWeight(2,2)+  CategoricalTree<Int> tree <- CategoricalTree<Int>.new().setWeight(1, 1).setWeight(2, 2)    CategoricalTree<Int> copy <- tree.duplicate()-  \ Testing.checkEquals(copy.size(),3)-  \ Testing.checkEquals(copy.getWeight(1),1)-  \ Testing.checkEquals(copy.getWeight(2),2)+  \ copy.size() `Matches:with` CheckValue:equals(3)+  \ copy.getWeight(1) `Matches:with` CheckValue:equals(1)+  \ copy.getWeight(2) `Matches:with` CheckValue:equals(2) -  \ copy.setWeight(2,0)-  \ Testing.checkEquals(copy.size(),1)-  \ Testing.checkEquals(copy.getWeight(1),1)-  \ Testing.checkEquals(tree.getWeight(2),2)+  \ copy.setWeight(2, 0)+  \ copy.size() `Matches:with` CheckValue:equals(1)+  \ copy.getWeight(1) `Matches:with` CheckValue:equals(1)+  \ tree.getWeight(2) `Matches:with` CheckValue:equals(2) }  unittest integrationTest { $DisableCoverage$   ValidatedTree<Int> tree     <- ValidatedTree<Int>.new()-  SortedMap<Int,Int> expected <- SortedMap<Int,Int>.new()+  SortedMap<Int, Int> expected <- SortedMap<Int, Int>.new()    Int count   <- 137   Int maxSize <- 15   Int hash1   <- 379   Int hash2   <- 457-  $ReadOnly[count,maxSize,hash1,hash2]$+  $ReadOnly[count, maxSize, hash1, hash2]$    // Populate the tree with arbitrary data.   traverse (Counter.zeroIndexed(count) -> Int i) {-    \ tree.setWeight((i*hash1)%count,(i*hash2)%maxSize)+    \ tree.setWeight((i*hash1)%count, (i*hash2)%maxSize)   }    // Overwrite the tree with real data.   traverse (Counter.zeroIndexed(count) -> Int i) {     Int key <- (i*hash2)%count     Int size <- (i*hash1)%maxSize-    \ tree.setWeight(key,size)-    \ expected.set(key,size)+    \ tree.setWeight(key, size)+    \ expected.set(key, size)   } -  optional Order<KeyValue<Int,Int>> node <- expected.defaultOrder()+  optional Order<KeyValue<Int, Int>> node <- expected.defaultOrder()   Int key       <- 0   Int remaining <- 0   traverse (Counter.zeroIndexed(tree.getTotal()) -> Int pos) {@@ -159,27 +159,27 @@     }     $ReadOnly[key]$     $Hidden[node]$-    \ Testing.checkEquals(tree.locate(pos),key)+    \ tree.locate(pos) `Matches:with` CheckValue:equals(key)     remaining <- remaining-1   } -  \ Testing.checkEmpty(node)-  \ Testing.checkEquals(remaining,0)+  \ present(node) `Matches:with` CheckValue:equals(false)+  \ remaining `Matches:with` CheckValue:equals(0) }   testcase "negative size crashes" {-  crash+  failure   require "size.+negative" }  unittest test {-  \ CategoricalTree<Int>.new().setWeight(0,-10)+  \ CategoricalTree<Int>.new().setWeight(0, -10) }   testcase "negative position crashes" {-  crash+  failure   require "position.+negative" } @@ -189,10 +189,10 @@   testcase "position past end crashes" {-  crash+  failure   require "position.+total" }  unittest test {-  \ CategoricalTree<Int>.new().setWeight(0,1).locate(1)+  \ CategoricalTree<Int>.new().setWeight(0, 1).locate(1) }
lib/math/test/math.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2020 Kevin P. Barry+Copyright 2020,2023 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.@@ -17,103 +17,103 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "sanity check all functions" {-  success+  success TestChecker }  unittest cos {-  \ Testing.checkBetween(Math.cos(2.0),-0.42,-0.41)+  \ Math.cos(2.0) `Matches:with` CheckValue:betweenEquals(-0.42, -0.41) }  unittest sin {-  \ Testing.checkBetween(Math.sin(2.0),0.90,0.91)+  \ Math.sin(2.0) `Matches:with` CheckValue:betweenEquals(0.90, 0.91) }  unittest tan {-  \ Testing.checkBetween(Math.tan(2.0),-2.19,-2.18)+  \ Math.tan(2.0) `Matches:with` CheckValue:betweenEquals(-2.19, -2.18) }  unittest acos {-  \ Testing.checkBetween(Math.acos(0.5),1.04,1.05)+  \ Math.acos(0.5) `Matches:with` CheckValue:betweenEquals(1.04, 1.05) }  unittest asin {-  \ Testing.checkBetween(Math.asin(0.5),0.52,0.53)+  \ Math.asin(0.5) `Matches:with` CheckValue:betweenEquals(0.52, 0.53) }  unittest atan {-  \ Testing.checkBetween(Math.atan(0.5),0.46,0.47)+  \ Math.atan(0.5) `Matches:with` CheckValue:betweenEquals(0.46, 0.47) }  unittest cosh {-  \ Testing.checkBetween(Math.cosh(2.0),3.76,3.77)+  \ Math.cosh(2.0) `Matches:with` CheckValue:betweenEquals(3.76, 3.77) }  unittest sinh {-  \ Testing.checkBetween(Math.sinh(2.0),3.62,3.63)+  \ Math.sinh(2.0) `Matches:with` CheckValue:betweenEquals(3.62, 3.63) }  unittest tanh {-  \ Testing.checkBetween(Math.tanh(2.0),0.96,0.97)+  \ Math.tanh(2.0) `Matches:with` CheckValue:betweenEquals(0.96, 0.97) }  unittest acosh {-  \ Testing.checkBetween(Math.acosh(2.0),1.31,1.32)+  \ Math.acosh(2.0) `Matches:with` CheckValue:betweenEquals(1.31, 1.32) }  unittest asinh {-  \ Testing.checkBetween(Math.asinh(2.0),1.44,1.45)+  \ Math.asinh(2.0) `Matches:with` CheckValue:betweenEquals(1.44, 1.45) }  unittest atanh {-  \ Testing.checkBetween(Math.atanh(0.5),0.54,0.55)+  \ Math.atanh(0.5) `Matches:with` CheckValue:betweenEquals(0.54, 0.55) }  unittest exp {-  \ Testing.checkBetween(Math.exp(1.0),2.71,2.72)+  \ Math.exp(1.0) `Matches:with` CheckValue:betweenEquals(2.71, 2.72) }  unittest log {-  \ Testing.checkBetween(Math.log(9.0),2.19,2.20)+  \ Math.log(9.0) `Matches:with` CheckValue:betweenEquals(2.19, 2.20) }  unittest log10 {-  \ Testing.checkBetween(Math.log10(100.0),1.99,2.01)+  \ Math.log10(100.0) `Matches:with` CheckValue:betweenEquals(1.99, 2.01) }  unittest log2 {-  \ Testing.checkBetween(Math.log2(8.0),2.99,3.01)+  \ Math.log2(8.0) `Matches:with` CheckValue:betweenEquals(2.99, 3.01) }  unittest pow {-  \ Testing.checkBetween(Math.pow(2.0,3.0),7.99,8.01)+  \ Math.pow(2.0, 3.0) `Matches:with` CheckValue:betweenEquals(7.99, 8.01) }  unittest sqrt {-  \ Testing.checkBetween(Math.sqrt(4.0),1.99,2.01)+  \ Math.sqrt(4.0) `Matches:with` CheckValue:betweenEquals(1.99, 2.01) }  unittest ceil {-  \ Testing.checkBetween(Math.ceil(2.2),2.99,3.01)+  \ Math.ceil(2.2) `Matches:with` CheckValue:betweenEquals(2.99, 3.01) }  unittest floor {-  \ Testing.checkBetween(Math.floor(2.2),1.99,2.01)+  \ Math.floor(2.2) `Matches:with` CheckValue:betweenEquals(1.99, 2.01) }  unittest fmod {-  \ Testing.checkBetween(Math.fmod(7.0,4.0),2.99,3.01)+  \ Math.fmod(7.0, 4.0) `Matches:with` CheckValue:betweenEquals(2.99, 3.01) }  unittest trunc {-  \ Testing.checkBetween(Math.trunc(2.2),1.99,2.01)+  \ Math.trunc(2.2) `Matches:with` CheckValue:betweenEquals(1.99, 2.01) }  unittest round {-  \ Testing.checkBetween(Math.round(2.7),2.99,3.01)+  \ Math.round(2.7) `Matches:with` CheckValue:betweenEquals(2.99, 3.01) }  unittest fabs {-  \ Testing.checkBetween(Math.fabs(-10.0),9.99,10.01)+  \ Math.fabs(-10.0) `Matches:with` CheckValue:betweenEquals(9.99, 10.01) }  unittest isinf {@@ -129,7 +129,7 @@ }  unittest abs {-  \ Testing.checkEquals(Math.abs(-10),10)-  \ Testing.checkEquals(Math.abs(10),10)-  \ Testing.checkEquals(Math.abs(0),0)+  \ Math.abs(-10) `Matches:with` CheckValue:equals(10)+  \ Math.abs(10) `Matches:with` CheckValue:equals(10)+  \ Math.abs(0) `Matches:with` CheckValue:equals(0) }
lib/math/test/random.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,7 +17,7 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "valid instantiations" {-  success+  success TestChecker }  unittest exponential {@@ -26,12 +26,12 @@ }  unittest gaussian {-  Generator<Float> random <- RandomGaussian.new(0.0,1.0)+  Generator<Float> random <- RandomGaussian.new(0.0, 1.0)   Float value <- random.generate() }  unittest uniform {-  Generator<Float> random <- RandomUniform.new(0.0,1.0)+  Generator<Float> random <- RandomUniform.new(0.0, 1.0)   Float value <- random.generate() } @@ -47,19 +47,19 @@  unittest categorical {   CategoricalTree<Float> tree <- CategoricalTree<Float>.new()-      .setWeight(0.0,1)-      .setWeight(1.0,1)-      .setWeight(2.0,1)-      .setWeight(3.0,1)-      .setWeight(4.0,1)+      .setWeight(0.0, 1)+      .setWeight(1.0, 1)+      .setWeight(2.0, 1)+      .setWeight(3.0, 1)+      .setWeight(4.0, 1)   RandomCategorical<Float> random <- tree `RandomCategorical:sampleWith` RandomUniform.probability()-  \ Testing.checkFalse(random.isEmpty())+  \ random.isEmpty() `Matches:with` CheckValue:equals(false)   Float value <- random.generate() }   testcase "negative lambda in exponential" {-  crash+  failure   require "lambda"   require "-1" }@@ -70,93 +70,93 @@   testcase "negative standard deviation in gaussian" {-  crash+  failure   require "standard deviation"   require "-1" }  unittest test {-  Generator<Float> random <- RandomGaussian.new(0.0,-1.0)+  Generator<Float> random <- RandomGaussian.new(0.0, -1.0) }   testcase "empty range in uniform" {-  crash+  failure   require "range"   require "0,-1" }  unittest test {-  Generator<Float> random <- RandomUniform.new(0.0,-1.0)+  Generator<Float> random <- RandomUniform.new(0.0, -1.0) }   testcase "sampling with empty CategoricalTree" {-  crash+  failure TestChecker   require "less than the total" }  unittest categorical {   CategoricalTree<Float> tree <- CategoricalTree<Float>.new()   RandomCategorical<Float> random <- tree `RandomCategorical:sampleWith` RandomUniform.probability()-  \ Testing.checkTrue(random.isEmpty())+  \ random.isEmpty() `Matches:with` CheckValue:equals(true)   Float value <- random.generate() }   testcase "distribution sanity checks" {-  success+  success TestChecker }  unittest exponential { $DisableCoverage$   Int count <- 10000   Float lambda <- 10.0-  $ReadOnly[count,lambda]$+  $ReadOnly[count, lambda]$    Generator<Float> random <- RandomExponential.new(lambda)    Float sum <- 0.0   traverse (Counter.zeroIndexed(count) -> _) {     Float value <- random.generate()-    \ Testing.checkGreaterThan(value,0.0)+    \ value `Matches:with` CheckValue:greaterThanNotEquals(0.0)     sum <- sum+value   } -  \ Testing.checkBetween(sum/count.asFloat(),0.9/lambda,1.1/lambda)+  \ sum/count.asFloat() `Matches:with` CheckValue:betweenEquals(0.9/lambda, 1.1/lambda) }  unittest gaussian { $DisableCoverage$   Int count <- 10000   Float mean <- 100.0   Float sd <- 1.0-  $ReadOnly[count,mean,sd]$+  $ReadOnly[count, mean, sd]$ -  Generator<Float> random <- RandomGaussian.new(mean,sd)+  Generator<Float> random <- RandomGaussian.new(mean, sd)    Float sum <- 0.0   traverse (Counter.zeroIndexed(count) -> _) {     sum <- sum+random.generate()   } -  \ Testing.checkBetween(sum/count.asFloat(),mean-0.1*sd,mean+0.1*sd)+  \ sum/count.asFloat() `Matches:with` CheckValue:betweenEquals(mean-0.1*sd, mean+0.1*sd) }  unittest uniform { $DisableCoverage$   Int count <- 10000   Float min <- -11.0   Float max <- 5.0-  $ReadOnly[count,min,max]$+  $ReadOnly[count, min, max]$ -  Generator<Float> random <- RandomUniform.new(min,max)+  Generator<Float> random <- RandomUniform.new(min, max)    Float sum <- 0.0   traverse (Counter.zeroIndexed(count) -> _) {     Float value <- random.generate()-    \ Testing.checkBetween(value,min,max)+    \ value `Matches:with` CheckValue:betweenEquals(min, max)     sum <- sum+value   } -  \ Testing.checkBetween(sum/count.asFloat(),(min+max)/2.0-0.1*(max-min),(min+max)/2.0+0.1*(max-min))+  \ sum/count.asFloat() `Matches:with` CheckValue:betweenEquals((min+max)/2.0-0.1*(max-min), (min+max)/2.0+0.1*(max-min)) }  unittest probability { $DisableCoverage$@@ -168,51 +168,51 @@   Float sum <- 0.0   traverse (Counter.zeroIndexed(count) -> _) {     Float value <- random.generate()-    \ Testing.checkBetween(value,0.0,1.0)+    \ value `Matches:with` CheckValue:betweenEquals(0.0, 1.0)     sum <- sum+value   } -  \ Testing.checkBetween(sum/count.asFloat(),0.4,0.6)+  \ sum/count.asFloat() `Matches:with` CheckValue:betweenEquals(0.4, 0.6) }  unittest constant { $DisableCoverage$   Int count <- 10000   Float constant <- 12345.0-  $ReadOnly[count,constant]$+  $ReadOnly[count, constant]$    Generator<Float> random <- GenerateConstant.new(constant)    traverse (Counter.zeroIndexed(count) -> _) {     Float value <- random.generate()-    \ Testing.checkEquals(constant,value)+    \ constant `Matches:with` CheckValue:equals(value)   } }  unittest categorical { $DisableCoverage$   Int count <- 10000   CategoricalTree<Float> tree <- CategoricalTree<Float>.new()-      .setWeight(0.0,1)-      .setWeight(1.0,1)-      .setWeight(2.0,1)-      .setWeight(3.0,1)-      .setWeight(4.0,1)-  $ReadOnly[count,tree]$+      .setWeight(0.0, 1)+      .setWeight(1.0, 1)+      .setWeight(2.0, 1)+      .setWeight(3.0, 1)+      .setWeight(4.0, 1)+  $ReadOnly[count, tree]$    Generator<Float> random <- tree `RandomCategorical:sampleWith` RandomUniform.probability()    Float sum <- 0.0   traverse (Counter.zeroIndexed(count) -> _) {     Float value <- random.generate()-    \ Testing.checkBetween(value,0.0,4.0)+    \ value `Matches:with` CheckValue:betweenEquals(0.0, 4.0)     sum <- sum+value   } -  \ Testing.checkBetween(sum/count.asFloat(),1.9,2.1)+  \ sum/count.asFloat() `Matches:with` CheckValue:betweenEquals(1.9, 2.1) }   testcase "distribution seed checks" {-  success+  success TestChecker }  unittest exponential {@@ -229,18 +229,18 @@   random2 <- random2.setSeed(123)   Float v4 <- random2.generate() -  \ Testing.checkNotEquals(v1,v2)-  \ Testing.checkNotEquals(v1,v3)-  \ Testing.checkEquals(v3,v4)+  \ v1 `Matches:with` CheckValue:notEquals(v2)+  \ v1 `Matches:with` CheckValue:notEquals(v3)+  \ v3 `Matches:with` CheckValue:equals(v4) }  unittest gaussian {   Float mean <- 100.0   Float sd <- 1.0-  $ReadOnly[mean,sd]$+  $ReadOnly[mean, sd]$ -  RandomGaussian random1 <- RandomGaussian.new(mean,sd)-  RandomGaussian random2 <- RandomGaussian.new(mean,sd)+  RandomGaussian random1 <- RandomGaussian.new(mean, sd)+  RandomGaussian random2 <- RandomGaussian.new(mean, sd)    Float v1 <- random1.generate()   Float v2 <- random2.generate()@@ -249,18 +249,18 @@   random2 <- random2.setSeed(123)   Float v4 <- random2.generate() -  \ Testing.checkNotEquals(v1,v2)-  \ Testing.checkNotEquals(v1,v3)-  \ Testing.checkEquals(v3,v4)+  \ v1 `Matches:with` CheckValue:notEquals(v2)+  \ v1 `Matches:with` CheckValue:notEquals(v3)+  \ v3 `Matches:with` CheckValue:equals(v4) }  unittest uniform {   Float min <- -11.0   Float max <- 5.0-  $ReadOnly[min,max]$+  $ReadOnly[min, max]$ -  RandomUniform random1 <- RandomUniform.new(min,max)-  RandomUniform random2 <- RandomUniform.new(min,max)+  RandomUniform random1 <- RandomUniform.new(min, max)+  RandomUniform random2 <- RandomUniform.new(min, max)    Float v1 <- random1.generate()   Float v2 <- random2.generate()@@ -269,21 +269,21 @@   random2 <- random2.setSeed(123)   Float v4 <- random2.generate() -  \ Testing.checkNotEquals(v1,v2)-  \ Testing.checkNotEquals(v1,v3)-  \ Testing.checkEquals(v3,v4)+  \ v1 `Matches:with` CheckValue:notEquals(v2)+  \ v1 `Matches:with` CheckValue:notEquals(v3)+  \ v3 `Matches:with` CheckValue:equals(v4) }   testcase "Randomize tests" {-  success+  success TestChecker }  unittest permuteFrom {   CategoricalTree<String> tree <- CategoricalTree<String>.new()-      .setWeight("a",2)-      .setWeight("b",3)-      .setWeight("c",1)+      .setWeight("a", 2)+      .setWeight("b", 3)+      .setWeight("c", 1)    Vector<String> expected <- Vector<String>.new()       .append("a")@@ -294,24 +294,24 @@       .append("c")    Vector<String> output <- Vector<String>.new()-  \ Randomize:permuteFrom(tree,RandomUniform.new(0.0,1.0),output)+  \ Randomize:permuteFrom(tree, RandomUniform.new(0.0, 1.0), output)   \ Sorting:sort(output) -  \ Testing.checkEquals(output.size(),expected.size())+  \ output.size() `Matches:with` CheckValue:equals(expected.size())   traverse (Counter.zeroIndexed(output.size()) -> Int pos) {-    \ Testing.checkEquals(output.readAt(pos),expected.readAt(pos))+    \ output.readAt(pos) `Matches:with` CheckValue:equals(expected.readAt(pos))   } -  \ Testing.checkEquals(tree.getWeight("a"),2)-  \ Testing.checkEquals(tree.getWeight("b"),3)-  \ Testing.checkEquals(tree.getWeight("c"),1)+  \ tree.getWeight("a") `Matches:with` CheckValue:equals(2)+  \ tree.getWeight("b") `Matches:with` CheckValue:equals(3)+  \ tree.getWeight("c") `Matches:with` CheckValue:equals(1) }  unittest permuteFromWeight {   CategoricalTree<String> tree <- CategoricalTree<String>.new()-      .setWeight("a",2)-      .setWeight("b",3)-      .setWeight("c",1)+      .setWeight("a", 2)+      .setWeight("b", 3)+      .setWeight("c", 1)    Vector<String> expected <- Vector<String>.new()       .append("a")@@ -319,15 +319,15 @@       .append("c")    Vector<String> output <- Vector<String>.new()-  \ Randomize:permuteFromWeight(tree,RandomUniform.new(0.0,1.0),output)+  \ Randomize:permuteFromWeight(tree, RandomUniform.new(0.0, 1.0), output)   \ Sorting:sort(output) -  \ Testing.checkEquals(output.size(),expected.size())+  \ output.size() `Matches:with` CheckValue:equals(expected.size())   traverse (Counter.zeroIndexed(output.size()) -> Int pos) {-    \ Testing.checkEquals(output.readAt(pos),expected.readAt(pos))+    \ output.readAt(pos) `Matches:with` CheckValue:equals(expected.readAt(pos))   } -  \ Testing.checkEquals(tree.getWeight("a"),2)-  \ Testing.checkEquals(tree.getWeight("b"),3)-  \ Testing.checkEquals(tree.getWeight("c"),1)+  \ tree.getWeight("a") `Matches:with` CheckValue:equals(2)+  \ tree.getWeight("b") `Matches:with` CheckValue:equals(3)+  \ tree.getWeight("c") `Matches:with` CheckValue:equals(1) }
lib/math/test/token.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,26 +17,26 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "basic Token tests" {-  success+  success TestChecker }  unittest equals {-  \ Testing.checkEquals(Token.from("message"),Token.from("message"))-  \ Testing.checkFalse(Token.from("message") `Token.equals` Token.from("other"))+  \ Token.from("message") `Matches:with` CheckValue:equals(Token.from("message"))+  \ Token.from("message") `Token.equals` Token.from("other") `Matches:with` CheckValue:equals(false) }  unittest lessThan {-  \ Testing.checkFalse(Token.from("message") `Token.lessThan` Token.from("message"))-  \ Testing.checkTrue((Token.from("message") `Token.lessThan` Token.from("other")) ||-                      (Token.from("other") `Token.lessThan` Token.from("message")))+  \ Token.from("message") `Token.lessThan` Token.from("message") `Matches:with` CheckValue:equals(false)+  \ ((Token.from("message") `Token.lessThan` Token.from("other")) ^+     (Token.from("other") `Token.lessThan` Token.from("message"))) `Matches:with` CheckValue:equals(true) }  unittest formatted {-  \ Testing.checkEquals(Token.from("message").formatted(),"message")+  \ Token.from("message").formatted() `Matches:with` CheckValue:equals("message") }  unittest hashed {-  \ Testing.checkNotEquals(Token.from("message").hashed(),Token.from("other").hashed())-  \ Testing.checkNotEquals(Token.from("message").hashed(),"message".hashed())-  \ Testing.checkEquals(Token.from("message").hashed(),Token.from("message").hashed())+  \ Token.from("message").hashed() `Matches:with` CheckValue:notEquals(Token.from("other").hashed())+  \ Token.from("message").hashed() `Matches:with` CheckValue:notEquals("message".hashed())+  \ Token.from("message").hashed() `Matches:with` CheckValue:equals(Token.from("message").hashed()) }
lib/testing/.zeolite-module view
@@ -1,7 +1,19 @@ root: "../.." path: "lib/testing"+expression_map: [+  expression_macro {+    name: FLOAT_RELATIVE_THRESHOLD+    expression: 1.0E-7+  }+] extra_paths: [   "lib/testing/src"   "lib/testing/test" ]-mode: incremental {}+extra_files: [+  category_source {+    source: "lib/testing/src/Extension_TestHandler.cpp"+    categories: [TestHandler]+  }+]+mode: incremental { }
+ lib/testing/check-float.0rp view
@@ -0,0 +1,28 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++// Simple Float checks.+concrete CheckFloat {+  // Uses relative threshold of $ExprLookup[FLOAT_RELATIVE_THRESHOLD]$ times the+  // max absolute value of the values being compared.+  // NOTE: This will never match 0 unless exactly 0 is expected.+  @category almostEquals (AsFloat) -> (ValueMatcher<[AsFloat & Formatted]>)++  // Uses absolute threshold.+  @category closeTo (AsFloat, Float epsilon:) -> (ValueMatcher<[AsFloat & Formatted]>)+}
+ lib/testing/check-sequence.0rp view
@@ -0,0 +1,33 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++// Checks sequences of values.+concrete CheckSequence {+  @category using<#x>+    #x requires TestCompare<#x>+  (DefaultOrder<#x>) -> (DefaultOrder<ValueMatcher<#x>>)++  @category equals<#x>+    #x requires Formatted+    #x defines Equals<#x>+  (DefaultOrder<#x>) -> (ValueMatcher<DefaultOrder<#x>>)++  @category matches<#x> (DefaultOrder<ValueMatcher<#x>>) -> (ValueMatcher<DefaultOrder<#x>>)++  @category allMatch<#x> (ValueMatcher<#x>) -> (ValueMatcher<DefaultOrder<#x>>)+}
+ lib/testing/check-string.0rp view
@@ -0,0 +1,24 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++// Simple sub-string checks.+concrete CheckString {+  @category contains (Formatted) -> (ValueMatcher<Formatted>)+  @category startsWith (Formatted) -> (ValueMatcher<Formatted>)+  @category endsWith (Formatted) -> (ValueMatcher<Formatted>)+}
+ lib/testing/check-value.0rp view
@@ -0,0 +1,67 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++// Simple equality-based value checks.+concrete CheckValue<#x|> {+  @category using<#x>+    #x requires TestCompare<#x>+  (#x) -> (ValueMatcher<#x>)++  @category equals<#x>+    #x requires Formatted+    #x defines Equals<#x>+  (optional #x) -> (ValueMatcher<#x>)++  @category notEquals<#x>+    #x requires Formatted+    #x defines Equals<#x>+  (optional #x) -> (ValueMatcher<#x>)++  // Value has the same Identifier.+  @category is<#x> (optional #x) -> (ValueMatcher<#x>)++  @category lessThanNotEquals<#x>+    #x requires Formatted+    #x defines LessThan<#x>+  (#x) -> (ValueMatcher<#x>)++  @category greaterThanNotEquals<#x>+    #x requires Formatted+    #x defines LessThan<#x>+  (#x) -> (ValueMatcher<#x>)++  @category betweenNotEquals<#x>+    #x requires Formatted+    #x defines LessThan<#x>+  (#x, #x) -> (ValueMatcher<#x>)++  @category lessThanEquals<#x>+    #x requires Formatted+    #x defines LessThan<#x>+  (#x) -> (ValueMatcher<#x>)++  @category greaterThanEquals<#x>+    #x requires Formatted+    #x defines LessThan<#x>+  (#x) -> (ValueMatcher<#x>)++  @category betweenEquals<#x>+    #x requires Formatted+    #x defines LessThan<#x>+  (#x, #x) -> (ValueMatcher<#x>)+}
+ lib/testing/checker.0rp view
@@ -0,0 +1,32 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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$++// NOTE: You must set the testcase checker in order to use this.+//+// testcase "my testcase" {+//    success TestChecker+// }+concrete TestChecker {+  defines Testcase++  @type isFailing () -> (Bool)+  @type checkNow () -> ()+  @type newReport (Formatted title:, optional Order<Formatted> context:) -> (TestReport)+}
+ lib/testing/evaluation.0rp view
@@ -0,0 +1,54 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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$++// NOTE: You must specify TestChecker in order to use this.+//+// testcase "my testcase" {+//    success TestChecker+// }+concrete Matches {+  // Fails immediately if match fails.+  @category with<#x> (optional #x, ValueMatcher<#x>) -> ()++  // Fails later if match fails.+  @category tryWith<#x> (optional #x, ValueMatcher<#x>) -> ()++  // Fails immediately if match fails.+  @category value<#x>+    #x requires TestCompare<#x>+  (optional #x, #x) -> ()++  // Fails later if match fails.+  @category tryValue<#x>+    #x requires TestCompare<#x>+  (optional #x, #x) -> ()+}++// Unconditional outcomes regardless of the actual value.+concrete CheckAlways {+  // Unconditionally match.+  @category match () -> (ValueMatcher<any>)++  // Unconditional error.+  @category error (Formatted) -> (ValueMatcher<any>)++  // Immediate crash if the matcher is used to check a value.+  @category die (Formatted) -> (ValueMatcher<any>)+}
− lib/testing/helpers.0rp
@@ -1,127 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2020-2021 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$--// General helpers for use in unit tests.-concrete Testing {-  // Check the values for equality. Crashes if they are not equal.-  //-  // Args:-  // - #x: Actual value.-  // - #x: Expected value.-  @type checkEquals<#x>-    #x requires Formatted-    #x defines Equals<#x>-  (#x,#x) -> ()--  // Check the values for inequality. Crashes if they are equal.-  //-  // Args:-  // - #x: Actual value.-  // - #x: Expected value.-  @type checkNotEquals<#x>-    #x requires Formatted-    #x defines Equals<#x>-  (#x,#x) -> ()--  // Check the value for empty. Crashes if present.-  //-  // Args:-  // - #x: Actual value.-  @type checkEmpty<#x> (optional #x) -> ()--  // Check the value for present. Crashes if empty.-  //-  // Args:-  // - optional any: Actual value.-  @type checkPresent (optional any) -> ()--  // Check the optional values for equality. Crashes if they are not equal.-  //-  // Args:-  // - optional #x: Actual value.-  // - optional #x: Expected value.-  @type checkOptional<#x>-    #x requires Formatted-    #x defines Equals<#x>-  (optional #x,optional #x) -> ()--  // Check the value for true. Crashes if false.-  //-  // Args:-  // - AsBool: Actual value.-  @type checkTrue (AsBool) -> ()--  // Check the value for false. Crashes if true.-  //-  // Args:-  // - AsBool: Actual value.-  @type checkFalse (AsBool) -> ()--  // Check that the value is within a range. Crashes if it is not in the range.-  //-  // Args:-  // - #x: Actual value.-  // - #x: Lower bound.-  // - #x: Upper bound.-  //-  // Notes:-  // - This could be done without Equals, except that some types have-  //   "undefined" values (e.g., NaN, for Float) that prevent inferring equality-  //   from less-than comparisons.-  @type checkBetween<#x>-    #x requires Formatted-    #x defines Equals<#x>-    #x defines LessThan<#x>-  (#x,#x,#x) -> ()--  // Check that the value is above the limit. Crashes if it is not in the range.-  //-  // Args:-  // - #x: Actual value.-  // - #x: Lower bound.-  //-  // Notes:-  // - This could be done without Equals, except that some types have-  //   "undefined" values (e.g., NaN, for Float) that prevent inferring equality-  //   from less-than comparisons.-  // - This comparison doesn't allow the value to equal the bound.-  @type checkGreaterThan<#x>-    #x requires Formatted-    #x defines Equals<#x>-    #x defines LessThan<#x>-  (#x,#x) -> ()--  // Check that the value is below the limit. Crashes if it is not in the range.-  //-  // Args:-  // - #x: Actual value.-  // - #x: Upper bound.-  //-  // Notes:-  // - This could be done without Equals, except that some types have-  //   "undefined" values (e.g., NaN, for Float) that prevent inferring equality-  //   from less-than comparisons.-  // - This comparison doesn't allow the value to equal the bound.-  @type checkLessThan<#x>-    #x requires Formatted-    #x defines Equals<#x>-    #x defines LessThan<#x>-  (#x,#x) -> ()-}
+ lib/testing/matching.0rp view
@@ -0,0 +1,66 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++// Supports test comparisons.+// NOTE: This should be refined in #x.+@value interface TestCompare<#x|> {+  testCompare (#x actual:, TestReport) -> ()+}++// Base interface for custom value matchers.+@value interface ValueMatcher<#x|> {+  check<#y>+    #y requires #x+  (optional #y, TestReport) -> ()++  summary () -> (Formatted)+}++// Interface used by predicate testers and matchers to report errors.+@value interface TestReport {+  // Adds a new error message.+  addError (Formatted message:) -> (#self)++  // Adds a child section without changing the error status.+  newSection (Formatted title:) -> (#self)++  // Discards error messages and child sections.+  discardReport () -> (#self)++  // Returns true if there are error messages, or if a child has an error.+  hasError () -> (Bool)+}++// Helper to check multiple members of a single object.+concrete MultiChecker {+  @value check<#x> (Formatted title:, optional #x, ValueMatcher<#x>) -> (optional #self)+  @value tryCheck<#x> (Formatted title:, optional #x, ValueMatcher<#x>) -> (#self)++  // Can only be constructed by value checkers.+  visibility ValueMatcher<all>, TestCompare<all>++  @type new (TestReport) -> (#self)+}++concrete MatcherCompose {+  @category not<#x> (ValueMatcher<#x>) -> (ValueMatcher<#x>)+  @category or<#x> (ValueMatcher<#x>, ValueMatcher<#x>) -> (ValueMatcher<#x>)+  @category and<#x> (ValueMatcher<#x>, ValueMatcher<#x>) -> (ValueMatcher<#x>)+  @category anyOf<#x> (DefaultOrder<ValueMatcher<#x>>) -> (ValueMatcher<#x>)+  @category allOf<#x> (DefaultOrder<ValueMatcher<#x>>) -> (ValueMatcher<#x>)+}
+ lib/testing/src/Extension_TestHandler.cpp view
@@ -0,0 +1,59 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++#include <cstdlib>+#include <iostream>++#include "category-source.hpp"+#include "Streamlined_TestHandler.hpp"+#include "Category_String.hpp"+#include "Category_TestHandler.hpp"++#ifdef ZEOLITE_PRIVATE_NAMESPACE+namespace ZEOLITE_PRIVATE_NAMESPACE {+#endif  // ZEOLITE_PRIVATE_NAMESPACE++struct ExtCategory_TestHandler : public Category_TestHandler {+  ReturnTuple Call_failAndExit(const ParamsArgs& params_args) final {+    TRACE_FUNCTION("TestHandler:failAndExit")+    const BoxedValue& Var_arg1 = params_args.GetArg(0);+    std::cerr << Var_arg1.AsString();+    std::exit(1);+  }+};++struct ExtType_TestHandler : public Type_TestHandler {+  inline ExtType_TestHandler(Category_TestHandler& p, Params<0>::Type params) : Type_TestHandler(p, params) {}+};++Category_TestHandler& CreateCategory_TestHandler() {+  static auto& category = *new ExtCategory_TestHandler();+  return category;+}++S<const Type_TestHandler> CreateType_TestHandler(const Params<0>::Type& params) {+  static const auto cached = S_get(new ExtType_TestHandler(CreateCategory_TestHandler(), Params<0>::Type()));+  return cached;+}++void RemoveType_TestHandler(const Params<0>::Type& params) {}++#ifdef ZEOLITE_PRIVATE_NAMESPACE+}  // namespace ZEOLITE_PRIVATE_NAMESPACE+using namespace ZEOLITE_PRIVATE_NAMESPACE;+#endif  // ZEOLITE_PRIVATE_NAMESPACE
+ lib/testing/src/check-float.0rx view
@@ -0,0 +1,92 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++define CheckFloat {+  $ReadOnlyExcept[]$++  refines ValueMatcher<[AsFloat & Formatted]>++  @value optional Float epsilon+  @value Float expected++  almostEquals (expected) {+    return CheckFloat{ empty, expected.asFloat() }+  }++  closeTo (expected, epsilon) {+    return CheckFloat{ epsilon, expected.asFloat() }+  }++  check (actual, report) {+    optional Float threshold <- epsilon+    if (`present` actual) {+      Float value <- require(actual).asFloat()+      $Hidden[actual]$+      if (`present` epsilon) {+        threshold <- `require` epsilon+      } else {+        threshold <- $ExprLookup[FLOAT_RELATIVE_THRESHOLD]$ * getMaxAbs(value, expected)+      }+      $Hidden[epsilon]$+      if (abs(value - expected) <= `require` threshold) {+        return _+      }+    }+    $Hidden[epsilon]$+    if (`present` threshold) {+      \ report.addError(message: String.builder()+          .append(`Format:autoFormat` actual)+          .append(" is not within ")+          .append(`require` threshold)+          .append(" of ")+          .append(expected)+          .build())+    } else {+      \ report.addError(message: String.builder()+          .append(`Format:autoFormat` actual)+          .append(" is not close to ")+          .append(expected)+          .build())+    }+  }++  summary () {+    if (`present` epsilon) {+      return "value is close to"+    } else {+      return "value is almost equal to"+    }+  }++  @type abs (Float) -> (Float)+  abs (x) {+    if (x < 0.0) {+      return -x+    } else {+      return x+    }+  }++  @type getMaxAbs (Float, Float) -> (Float)+  getMaxAbs (x, y) (max) {+    max <- abs(x)+    if (abs(y) > max) {+      max <- abs(y)+    }+  }+}
+ lib/testing/src/check-sequence.0rx view
@@ -0,0 +1,219 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++define CheckSequence {+  using (expected) {+    return SequenceAdapter<#x>.new(expected)+  }++  equals (expected) {+    return SequenceEquals<#x>.new(expected)+  }++  matches (expected) {+    return SequenceMatches<#x>.new(expected)+  }++  allMatch (expected) {+    return SequenceAllMatch<#x>.new(expected)+  }+}++concrete SequenceAdapter<#x> {+  #x requires TestCompare<#x>++  @type new (DefaultOrder<#x>) -> (DefaultOrder<ValueMatcher<#x>>)+}++define SequenceAdapter {+  $ReadOnlyExcept[current]$++  refines DefaultOrder<ValueMatcher<#x>>+  refines Order<ValueMatcher<#x>>++  @value DefaultOrder<#x> original+  @value optional Order<#x> current++  new (original) {+    return #self{ original, empty }+  }++  defaultOrder () {+    return #self{ original, original.defaultOrder() }+  }++  get () {+    return CheckValue:using(`require` current&.get())+  }++  next () {+    if (`present` (current <- current&.next())) {+      return self+    } else {+      return empty+    }+  }+}++concrete SequenceEquals<#x> {+  #x requires Formatted+  #x defines Equals<#x>++  @type new (DefaultOrder<#x>) -> (ValueMatcher<DefaultOrder<#x>>)+}++define SequenceEquals {+  $ReadOnlyExcept[]$++  refines ValueMatcher<DefaultOrder<#x>>++  @value DefaultOrder<#x> expected++  new (expected) {+    return delegate -> #self+  }++  check (actual, report) {+    optional Order<#x> currentActual   <- actual&.defaultOrder()+    optional Order<#x> currentExpected <- expected.defaultOrder()+    Int index <- 0+    $Hidden[actual, expected]$+    while (`present` currentActual || `present` currentExpected) {+      optional #x valueActual   <- currentActual&.get()+      optional #x valueExpected <- currentExpected&.get()+      TestReport newReport <- report.newSection(title: String.builder()+          .append("Item #")+          .append(index)+          .build())+      $Hidden[report]$+      if (! `present` valueActual) {+        \ newReport.addError(message: String.builder()+            .append(`Format:autoFormat` valueExpected)+            .append(" is missing")+            .build())+      } elif (! `present` valueExpected) {+        \ newReport.addError(message: String.builder()+            .append(`Format:autoFormat` valueActual)+            .append(" is unexpected")+            .build())+      } elif (!(require(valueActual) `#x.equals` require(valueExpected))) {+        \ newReport.addError(message: String.builder()+            .append(`Format:autoFormat` valueActual)+            .append(" does not equal ")+            .append(`Format:autoFormat` valueExpected)+            .build())+      }+    } update {+      currentActual <- currentActual&.next()+      currentExpected <- currentExpected&.next()+      index <- index+1+    }+  }++  summary () {+    return "sequence has equal values"+  }+}++concrete SequenceMatches<#x> {+  @type new (DefaultOrder<ValueMatcher<#x>>) -> (ValueMatcher<DefaultOrder<#x>>)+}++define SequenceMatches {+  $ReadOnlyExcept[]$++  refines ValueMatcher<DefaultOrder<#x>>++  @value DefaultOrder<ValueMatcher<#x>> expected++  new (expected) {+    return delegate -> #self+  }++  check (actual, report) {+    optional Order<#x> currentActual <- actual&.defaultOrder()+    optional Order<ValueMatcher<#x>> currentExpected <- expected.defaultOrder()+    Int index <- 0+    $Hidden[actual, expected]$+    while (`present` currentActual || `present` currentExpected) {+      optional #x valueActual <- currentActual&.get()+      optional ValueMatcher<#x> valueExpected <- currentExpected&.get()+      TestReport newReport <- report.newSection(title: String.builder()+          .append("Item #")+          .append(index)+          .build())+      $Hidden[report]$+      if (! `present` valueActual) {+        \ newReport.addError(message: String.builder()+            .append("Item #")+            .append(index)+            .append(" is missing")+            .build())+      } elif (! `present` valueExpected) {+        \ newReport.addError(message: String.builder()+            .append("Item #")+            .append(index)+            .append(" is unexpected")+            .build())+      } else {+        \ valueActual `require(valueExpected).check` newReport+      }+    } update {+      currentActual <- currentActual&.next()+      currentExpected <- currentExpected&.next()+      index <- index+1+    }+  }++  summary () {+    return "sequence values separately match"+  }+}++concrete SequenceAllMatch<#x> {+  @type new (ValueMatcher<#x>) -> (ValueMatcher<DefaultOrder<#x>>)+}++define SequenceAllMatch {+  $ReadOnlyExcept[]$++  refines ValueMatcher<DefaultOrder<#x>>++  @value ValueMatcher<#x> expected++  new (expected) {+    return delegate -> #self+  }++  check (actual, report) {+    scoped {+      Int index <- 0+    } in traverse (actual&.defaultOrder() -> #x value) {+      TestReport newReport <- report.newSection(title: String.builder()+          .append("Item #")+          .append(index)+          .build())+      $Hidden[report]$+      \ value `expected.check` newReport+    }+  }++  summary () {+    return "sequence values all match"+  }+}
+ lib/testing/src/check-string.0rx view
@@ -0,0 +1,96 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++define CheckString {+  $ReadOnlyExcept[]$++  refines ValueMatcher<Formatted>++  @value String expected+  @value Bool fromStart+  @value Bool toEnd++  contains (expected) {+    return CheckString{ expected.formatted(), false, false }+  }++  startsWith (expected) {+    return CheckString{ expected.formatted(), true, false }+  }++  endsWith (expected) {+    return CheckString{ expected.formatted(), false, true }+  }++  check (actual, report) {+    if (! `present` actual) {+      \ report.addError(message: appendErrorAndBuild(String.builder().append("empty")))+      return _+    }+    String value <- require(actual).formatted()+    $Hidden[actual]$+    Int startIndex <- 0+    if (toEnd) {+      startIndex <- value.size()-expected.size()+    }+    while (startIndex >= 0 && startIndex+expected.size() <= value.size()) {+      Bool matches <- true+      scoped {+        Int index <- startIndex+        $Hidden[startIndex]$+      } in traverse (expected.defaultOrder() -> Char char) {+        $Hidden[expected]$+        if (value.readAt(index) != char) {+          matches <- false+          break+        }+      } update {+        index <- index+1+      }+      if (matches) {+        return _+      } elif (fromStart || toEnd) {+        break+      }+    } update {+      startIndex <- startIndex+1+    }+    \ report.addError(message: appendErrorAndBuild(String.builder().append(`Format:autoFormat` value)))+  }++  summary () {+    if (fromStart) {+      return "String starts with"+    } elif (toEnd) {+      return "String ends with"+    } else {+      return "String contains"+    }+  }++  @value appendErrorAndBuild ([Append<Formatted> & Build<String>]) -> (String)+  appendErrorAndBuild (output) {+    if (fromStart) {+      return output.append(" does not start with ").append(`Format:autoFormat` expected).build()+    } elif (toEnd) {+      return output.append(" does not end with ").append(`Format:autoFormat` expected).build()+    } else {+      return output.append(" does not contain ").append(`Format:autoFormat` expected).build()+    }+  }+}
+ lib/testing/src/check-value.0rx view
@@ -0,0 +1,269 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++define CheckValue {+  using (expected) {+    return ValueTester<#x>.new(expected)+  }++  equals (expected) {+    return ValueEquals<#x>.new(false, expected)+  }++  notEquals (expected) {+    return ValueEquals<#x>.new(true, expected)+  }++  is (expected) {+    return ValueIdentifier<#x>.new(expected)+  }++  lessThanNotEquals (upper) {+    return ValueBounds<#x>.new(false, empty, upper)+  }++  greaterThanNotEquals (lower) {+    return ValueBounds<#x>.new(false, lower, empty)+  }++  betweenNotEquals (lower, upper) {+    return ValueBounds<#x>.new(false, lower, upper)+  }++  lessThanEquals (upper) {+    return ValueBounds<#x>.new(true, empty, upper)+  }++  greaterThanEquals (lower) {+    return ValueBounds<#x>.new(true, lower, empty)+  }++  betweenEquals (lower, upper) {+    return ValueBounds<#x>.new(true, lower, upper)+  }+}++concrete ValueTester<#x> {+  #x requires TestCompare<#x>++  @type new (#x) -> (ValueMatcher<#x>)+}++define ValueTester {+  $ReadOnlyExcept[]$++  refines ValueMatcher<#x>++  @value #x expected++  new (expected) {+    return delegate -> #self+  }++  check (actual, report) {+    if (! `present` actual) {+      \ report.addError(message: "expected value but got empty")+    } else {+      \ expected.testCompare(actual: require(actual), report)+    }+  }++  summary () {+    return String.builder()+        .append("matches ")+        .append(typename<#x>())+        .build()+  }+}++concrete ValueEquals<#x> {+  #x requires Formatted+  #x defines Equals<#x>++  @type new (Bool, optional #x) -> (ValueMatcher<#x>)+}++define ValueEquals {+  $ReadOnlyExcept[]$++  refines ValueMatcher<#x>++  @value Bool invert+  @value optional #x expected++  new (invert, expected) {+    return delegate -> #self+  }++  check (actual, report) {+    Bool match <- defer+    if (`present` actual && `present` expected) {+      match <- require(actual) `#x.equals` require(expected)+    } else {+      match <- ! `present` actual && ! `present` expected+    }+    if (invert && match) {+      \ report.addError(message: String.builder()+          .append(`Format:autoFormat` actual)+          .append(" equals ")+          .append(`Format:autoFormat` expected)+          .build())+    } elif (!invert && !match) {+      \ report.addError(message: String.builder()+          .append(`Format:autoFormat` actual)+          .append(" does not equal ")+          .append(`Format:autoFormat` expected)+          .build())+    }+  }++  summary () {+    if (invert) {+      return "value not equals"+    } else {+      return "value equals"+    }+  }+}++concrete ValueIdentifier<#x> {+  @type new (optional #x) -> (ValueMatcher<#x>)+}++define ValueIdentifier {+  $ReadOnlyExcept[]$++  refines ValueMatcher<#x>++  // NOTE: Don't use #x here so that it doesn't create a reference.+  @value Identifier<#x> expected++  new (expected) {+    return #self{ `identify` expected }+  }++  check (actual, report) {+    if (`identify` actual != expected) {+      \ report.addError(message: String.builder()+          .append(`format` `identify` actual)+          .append(" does not equal ")+          .append(`format` expected)+          .build())+    }+  }++  summary () {+    return "value is same instance as"+  }++  @type format (Identifier<#x>) -> (Formatted)+  format (id) {+    return String.builder()+        .append(typename<#x>())+        .append("@")+        .append(id)+        .build()+  }+}++concrete ValueBounds<#x> {+  #x requires Formatted+  #x defines LessThan<#x>++  @type new (Bool, optional #x, optional #x) -> (ValueMatcher<#x>)+}++define ValueBounds {+  $ReadOnlyExcept[]$++  refines ValueMatcher<#x>++  @value Bool inclusive+  @value optional #x lower+  @value optional #x upper++  new (inclusive, lower, upper) {+    return delegate -> #self+  }++  check (actual, report) {+    Bool match <- `present` actual+    if (match && `present` lower) {+      match <- require(lower) `compare` require(actual)+    }+    if (match && `present` upper) {+      match <- require(actual) `compare` require(upper)+    }+    if (!match) {+      if (`present` lower && `present` upper) {+        \ report.addError(message: String.builder()+            .append(`Format:autoFormat` actual)+            .append(" is not between ")+            .append(`Format:autoFormat` lower)+            .append(" and ")+            .append(`Format:autoFormat` upper)+            .build())+      } elif (`present` lower) {+        \ report.addError(message: String.builder()+            .append(`Format:autoFormat` actual)+            .append(" is not greater than ")+            .append(`Format:autoFormat` lower)+            .build())+      } elif (`present` upper) {+        \ report.addError(message: String.builder()+            .append(`Format:autoFormat` actual)+            .append(" is not less than ")+            .append(`Format:autoFormat` upper)+            .build())+      }+    }+  }++  summary () {+    if (inclusive) {+      if (`present` lower && `present` upper) {+        return "value is between or equal"+      } elif (`present` lower) {+        return "value is greater than or equal"+      } elif (`present` upper) {+        return "value is less than or equal"+      } else {+        return "value is present"+      }+    } else {+      if (`present` lower && `present` upper) {+        return "value is between but not equal"+      } elif (`present` lower) {+        return "value is greater than but not equal"+      } elif (`present` upper) {+        return "value is less than but not equal"+      } else {+        return "value is present"+      }+    }+  }++  @value compare (#x, #x) -> (Bool)+  compare (x, y) {+    if (inclusive) {+      return !(y `#x.lessThan` x)+    } else {+      return x `#x.lessThan` y+    }+  }+}
+ lib/testing/src/checker.0rx view
@@ -0,0 +1,110 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 TestChecker {+  @category Bool started <- false+  @category Bool inProgress <- false+  @category Int testCount <- 0+  @category ValueList<TestReportTree> reports <- ValueList<TestReportTree>.new()++  start () { $NoTrace$+    if (started) {+      fail("Testcase already started.")+    }+    started <- true+    inProgress <- true+  }++  finish () { $NoTrace$+    \ checkTestingStarted()+    if (inProgress) {+      inProgress <- false+      \ checkNow()+    }+  }++  isFailing () { $NoTrace$+    \ checkTestingStarted()+    traverse (reports.defaultOrder() -> TestReportTree report) {+      if (report.hasError()) {+        return true+      }+    }+    return false+  }++  checkNow () { $NoTrace$+    \ checkTestingStarted()+    if (isFailing()) {+      \ TestHandler:failAndExit(formatErrors().formatted())+    }+  }++  newReport (title, context) { $NoTrace$+    \ checkTestingAllowed()+    ValueList<Formatted> contextList <- ValueList<Formatted>.new()+    traverse (context -> Formatted item) {+      String stringItem <- item.formatted()+      // TODO: Get rid of this hard coding.+      if (stringItem == "From testcase") {+        break+      } else {+        \ contextList.append(stringItem)+      }+    }+    String numberedTitle <- String.builder()+        .append("Check #")+        .append((testCount <- testCount+1))+        .append(": ")+        .append(title)+        .build()+    TestReportTree report <- TestReportTree.new(numberedTitle, contextList)+    \ reports.append(report)+    return report+  }++  @category formatErrors () -> (Formatted)+  formatErrors () {+    IndentAppend output <- IndentAppend.new(String.builder())+    \ output.append("TestChecker failures:")+    scoped {+      \ output.pushIndent()+    } cleanup {+      \ output.popIndent()+    } in traverse (reports.defaultOrder() -> TestReportTree report) {+      \ report.prune()&.writeTo(output)&.addNewline()+    }+    return output.build()+  }++  @category checkTestingStarted () -> ()+  checkTestingStarted () {+    if (!started) {+      fail("Testcase was not started.")+    }+  }++  @category checkTestingAllowed () -> ()+  checkTestingAllowed () {+    if (!started || !inProgress) {+      fail("Testcase not started or no longer in progress.")+    }+  }+}
+ lib/testing/src/evaluation.0rx view
@@ -0,0 +1,109 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 Matches {+  with (value, matcher) { $NoTrace$+    if (delegate -> `executeMatch`) {+      \ TestChecker.checkNow()+    }+  }++  tryWith (value, matcher) { $NoTrace$+    \ delegate -> `executeMatch`+  }++  value (actual, expected) { $NoTrace$+    if (delegate -> `executeValue`) {+      \ TestChecker.checkNow()+    }+  }++  tryValue (actual, expected) { $NoTrace$+    \ delegate -> `executeValue`+  }++  @category executeMatch<#x> (optional #x, ValueMatcher<#x>) -> (Bool)+  executeMatch (value, matcher) { $NoTrace$+    String title <- String.builder()+        .append("Matches with ")+        .append(matcher.summary())+        .build()+    TestReport report <- TestChecker.newReport(title: title, context: $CallTrace$)+    \ value `matcher.check` report+    return report.hasError()+  }++  @category executeValue<#x>+    #x requires TestCompare<#x>+  (optional #x, #x) -> (Bool)+  executeValue (actual, expected) { $NoTrace$+    String title <- String.builder()+        .append("Matches ")+        .append(typename<#x>())+        .build()+    TestReport report <- TestChecker.newReport(title: title, context: $CallTrace$)+    if (! `present` actual) {+      \ report.addError(message: "expected value but got empty")+    } else {+      \ expected.testCompare(actual: require(actual), report)+    }+    return report.hasError()+  }+}++define CheckAlways {+  $ReadOnlyExcept[]$++  refines ValueMatcher<any>++  @value Bool die+  @value optional Formatted message++  match () {+    return CheckAlways{ false, empty }+  }++  error (message) {+    return CheckAlways{ false, message }+  }++  die (message) {+    return CheckAlways{ true, message }+  }++  check (_, report) {+    if (! `present` message) {+    } elif (die) {+      fail(`require` message)+    } else {+      \ report.addError(message: `require` message)+    }+  }++  summary () {+    if (die) {+      return "always die"+    } elif (`present` message) {+      return "always error"+    } else {+      return "always pass"+    }+  }+}
− lib/testing/src/helpers.0rx
@@ -1,135 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2020-2021 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) { $NoTrace$-    if (!#x.equals(x,y)) {-      fail(String.builder()-          .append(x)-          .append(" is not equal to ")-          .append(y)-          .build())-    }-  }--  checkNotEquals (x,y) { $NoTrace$-    if (#x.equals(x,y)) {-      fail(String.builder()-          .append(x)-          .append(" is equal to ")-          .append(y)-          .build())-    }-  }--  checkEmpty (x) { $NoTrace$-    if (present(x)) {-      scoped {-        optional Formatted formatted <- reduce<#x,Formatted>(require(x))-      } in if (present(formatted)) {-        fail(String.builder()-            .append(require(formatted))-            .append(" is not empty")-            .build())-      } else {-        fail("(unformatted value) is not empty")-      }-    }-  }--  checkPresent (x) { $NoTrace$-    if (!present(x)) {-      fail(String.builder()-          .append("expected non-empty value")-          .build())-    }-  }--  checkOptional (x,y) { $NoTrace$-    if (present(x) && present(y)) {-      \ checkEquals(require(x),require(y))-    } elif (!present(x) && present(y)) {-      fail("empty is not equal to " + require(y).formatted())-    } elif (present(x) && !present(y)) {-      fail(require(x).formatted() + " is not equal to empty")-    }-  }--  checkTrue (x) { $NoTrace$-    if (!x.asBool()) {-      fail("expected true")-    }-  }--  checkFalse (x) { $NoTrace$-    if (x.asBool()) {-      fail("expected false")-    }-  }--  checkBetween (x,l,h) { $NoTrace$-    if (!lessEquals(l,h)) {-      fail(String.builder()-          .append("Upper limit ")-          .append(l)-          .append(" is not at or above lower limit ")-          .append(h)-          .build())-    }-    if (!lessEquals(l,x) || !lessEquals(x,h)) {-      fail(String.builder()-          .append(x)-          .append(" is not between ")-          .append(l)-          .append(" and ")-          .append(h)-          .build())-    }-  }--  checkGreaterThan (x,l) { $NoTrace$-    if (lessEquals(x,l)) {-      fail(String.builder()-          .append(x)-          .append(" is not greater than ")-          .append(l)-          .build())-    }-  }--  checkLessThan (x,h) { $NoTrace$-    if (lessEquals(h,x)) {-      fail(String.builder()-          .append(x)-          .append(" is not less than ")-          .append(h)-          .build())-    }-  }--  @type lessEquals<#x>-    #x defines Equals<#x>-    #x defines LessThan<#x>-  (#x,#x) -> (Bool)-  lessEquals (x,y) { $NoTrace$-    // Using !#x.lessThan(y,x) wouldn't account for NaNs.-    return #x.lessThan(x,y) || #x.equals(x,y)-  }-}
+ lib/testing/src/matching.0rx view
@@ -0,0 +1,241 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++define MultiChecker {+  $ReadOnlyExcept[]$++  @value TestReport report++  new (report) {+    return delegate -> #self+  }++  check (title, value, matcher) {+    if (delegate -> `executeMatch`) {+      return empty+    } else {+      return self+    }+  }++  tryCheck (title, value, matcher) {+    \ delegate -> `executeMatch`+    return self+  }++  @value executeMatch<#x> (Formatted title:, optional #x, ValueMatcher<#x>) -> (Bool)+  executeMatch (title, value, matcher) {+    String fullTitle <- String.builder()+        .append(title)+        .append(": ")+        .append(matcher.summary())+        .build()+    TestReport newReport <- report.newSection(title: fullTitle)+    $Hidden[report]$+    \ value `matcher.check` newReport+    return newReport.hasError()+  }+}++define MatcherCompose {+  or (left, right) {+    return delegate -> `OrMatcher:new`+  }++  not (matcher) {+    return delegate -> `NotMatcher:new`+  }++  and (left, right) {+    return delegate -> `AndMatcher:new`+  }++  anyOf (matchers) {+    return delegate -> `AnyOfMatcher:new`+  }++  allOf (matchers) {+    return delegate -> `AllOfMatcher:new`+  }+}++concrete OrMatcher<#x|> {+  refines ValueMatcher<#x>++  @category new<#x> (ValueMatcher<#x>, ValueMatcher<#x>) -> (ValueMatcher<#x>)+}++define OrMatcher {+  @value ValueMatcher<#x> left+  @value ValueMatcher<#x> right++  new (left, right) {+    return delegate -> OrMatcher<#x>+  }++  check (actual, report) {+    TestReport leftReport <- report.newSection(title: left.summary())+    TestReport rightReport <- report.newSection(title: right.summary())+    \ actual `left.check` leftReport+    if (!leftReport.hasError()) {+      return _+    }+    $Hidden[left]$+    \ actual `right.check` rightReport+    if (!rightReport.hasError()) {+      \ leftReport.discardReport()+    }+  }++  summary () {+    return String.builder()+        .append("either (")+        .append(left.summary())+        .append(") or (")+        .append(right.summary())+        .append(")")+        .build()+  }+}++concrete NotMatcher<#x|> {+  refines ValueMatcher<#x>++  @category new<#x> (ValueMatcher<#x>) -> (ValueMatcher<#x>)+}++define NotMatcher {+  @value ValueMatcher<#x> matcher++  new (matcher) {+    return delegate -> NotMatcher<#x>+  }++  check (actual, report) {+    \ delegate -> `matcher.check`+    if (report.hasError()) {+      \ report.discardReport()+    } else {+      \ report.addError(message: String.builder()+          .append("expected failure to match with ")+          .append(matcher.summary())+          .build())+    }+  }++  summary () {+    return String.builder()+        .append("not (")+        .append(matcher.summary())+        .append(")")+        .build()+  }+}++concrete AndMatcher<#x|> {+  refines ValueMatcher<#x>++  @category new<#x> (ValueMatcher<#x>, ValueMatcher<#x>) -> (ValueMatcher<#x>)+}++define AndMatcher {+  @value ValueMatcher<#x> left+  @value ValueMatcher<#x> right++  new (left, right) {+    return delegate -> AndMatcher<#x>+  }++  check (actual, report) {+    TestReport leftReport <- report.newSection(title: left.summary())+    TestReport rightReport <- report.newSection(title: right.summary())+    \ actual `left.check` leftReport+    \ actual `right.check` rightReport+  }++  summary () {+    return String.builder()+        .append("both (")+        .append(left.summary())+        .append(") and (")+        .append(right.summary())+        .append(")")+        .build()+  }+}++concrete AnyOfMatcher<#x|> {+  refines ValueMatcher<#x>++  @category new<#x> (DefaultOrder<ValueMatcher<#x>>) -> (ValueMatcher<#x>)+}++define AnyOfMatcher {+  @value DefaultOrder<ValueMatcher<#x>> matchers++  new (matchers) {+    return delegate -> AnyOfMatcher<#x>+  }++  check (actual, report) {+    ValueList<TestReport> reports <- ValueList<TestReport>.new()+    traverse (matchers.defaultOrder() -> ValueMatcher<#x> matcher) {+      TestReport subReport <- report.newSection(title: matcher.summary())+      $Hidden[report]$+      \ actual `matcher.check` subReport+      if (subReport.hasError()) {+        \ reports.append(subReport)+      } else {+        traverse (reports.defaultOrder() -> TestReport failed) {+          \ failed.discardReport()+        }+        break+      }+    }+  }++  summary () {+    return "match any of"+  }+}++concrete AllOfMatcher<#x|> {+  refines ValueMatcher<#x>++  @category new<#x> (DefaultOrder<ValueMatcher<#x>>) -> (ValueMatcher<#x>)+}++define AllOfMatcher {+  @value DefaultOrder<ValueMatcher<#x>> matchers++  new (matchers) {+    return delegate -> AllOfMatcher<#x>+  }++  check (actual, report) {+    traverse (matchers.defaultOrder() -> ValueMatcher<#x> matcher) {+      TestReport subReport <- report.newSection(title: matcher.summary())+      $Hidden[report]$+      \ actual `matcher.check` subReport+    }+  }++  summary () {+    return "match all of"+  }+}
+ lib/testing/src/util.0rp view
@@ -0,0 +1,59 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++$ModuleOnly$++concrete IndentAppend {+  refines Append<Formatted>+  refines Build<Formatted>++  @type new ([Append<Formatted> & Build<Formatted>]) -> (#self)++  @value pushIndent () -> (#self)+  @value popIndent () -> (#self)+  @value addNewline () -> (#self)+}++concrete ValueList<#x> {+  refines Append<#x>+  refines DefaultOrder<#x>++  @type new () -> (#self)+  @value isEmpty () -> (Bool)+}++// See Extension_TestHandler.cpp.+concrete TestHandler {+  @category failAndExit (String) -> ()+}++concrete TestReportTree {+  refines TestReport++  @type new (Formatted, ValueList<Formatted>) -> (#self)++  // NOTE: This will write passing sections unless you prune() first.+  @value writeTo (IndentAppend) -> (IndentAppend)+  @value prune () -> (optional #self)+}++concrete Format {+  @category autoFormat<#x>+    #x requires Formatted+  (optional #x) -> (Formatted)+}
+ lib/testing/src/util.0rx view
@@ -0,0 +1,239 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++define IndentAppend {+  $ReadOnlyExcept[indentCount]$++  @value [Append<Formatted> & Build<Formatted>] output+  @value Int indentCount++  new (output) {+    return #self{ output, 0 }+  }++  pushIndent () {+    indentCount <- indentCount+1+    return self+  }++  popIndent () {+    indentCount <- indentCount-1+    return self+  }++  addNewline () {+    \ output.append("\n")+    return self+  }++  append (value) {+    scoped {+      Int count <- 0+    } in while (count < indentCount) {+      \ output.append("  ")+    } update {+      count <- count+1+    }+    \ output.append(value).append("\n")+    return self+  }++  build () {+    return output.build()+  }+}++concrete ListNode<#x> {+  refines Order<#x>++  @type new (#x) -> (#self)+  @value setNext (optional ListNode<#x>) -> (#self)+}++define ListNode {+  $FlatCleanup[next]$+  $ReadOnly[value]$++  @value #x value+  @value optional #self next++  new (value) {+    return #self{ value, empty }+  }++  setNext (newNext) {+    next <- newNext+    return self+  }++  next () {+    return next+  }++  get () {+    return value+  }+}++define ValueList {+  @value optional ListNode<#x> head+  @value optional ListNode<#x> tail++  new () {+    return #self{ empty, empty }+  }++  isEmpty () {+    return ! `present` head+  }++  append (value) {+    scoped {+      ListNode<#x> node <- ListNode<#x>.new(value)+    } in {+      head <-| node+      \ tail&.setNext(node)+      tail <- node+    }+    return self+  }++  defaultOrder () {+    return head+  }+}++define TestReportTree {+  $ReadOnlyExcept[messages, children]$++  @value Formatted title+  @value ValueList<Formatted> context+  @value ValueList<Formatted> messages+  @value ValueList<TestReportTree> children++  new (title, context) {+    return #self{ title, context, ValueList<Formatted>.new(), ValueList<TestReportTree>.new() }+  }++  writeTo (output) {+    \ output.append(title)+    scoped {+      \ output.pushIndent()+    } cleanup {+      \ output.popIndent()+    } in {+      \ writeMessagesTo(output)+      \ writeContextTo(output)+      \ writeChildrenTo(output)+    }+    return output+  }++  addError (message) {+    \ messages.append(message)+    return self+  }++  newSection (newTitle) {+    #self new <- new(newTitle, ValueList<Formatted>.new())+    \ children.append(new)+    return new+  }++  discardReport () {+    messages <- ValueList<Formatted>.new()+    children <- ValueList<TestReportTree>.new()+    return self+  }++  hasError () {+    if (!messages.isEmpty()) {+      return true+    }+    traverse (children.defaultOrder() -> TestReportTree child) {+      if (child.hasError()) {+        return true+      }+    }+    return false+  }++  prune () {+    optional ValueList<TestReportTree> newChildren <- empty+    traverse (children.defaultOrder() -> TestReportTree child) {+      $Hidden[children]$+      optional TestReportTree newChild <- child.prune()+      $Hidden[child]$+      if (`present` newChild) {+        \ (newChildren <-| ValueList<TestReportTree>.new()).append(`require` newChild)+      }+    }+    if (! `present` newChildren && messages.isEmpty()) {+      children <- ValueList<TestReportTree>.new()+      return empty+    } else {+      children <- (newChildren <-| ValueList<TestReportTree>.new())+      return self+    }+  }++  @value writeContextTo (IndentAppend) -> ()+  writeContextTo (output) {+    $Hidden[messages, children]$+      scoped {+      \ output.pushIndent()+    } cleanup {+      \ output.popIndent()+    } in traverse (context.defaultOrder() -> Formatted line) {+      \ output.append(line)+    }+  }++  @value writeMessagesTo (IndentAppend) -> ()+  writeMessagesTo (output) {+    $Hidden[context, children]$+    if (!messages.isEmpty()) {+      traverse (messages.defaultOrder() -> Formatted line) {+        \ output.append(line)+      }+    }+  }++  @value writeChildrenTo (IndentAppend) -> ()+  writeChildrenTo (output) {+    $Hidden[messages, context]$+    traverse (children.defaultOrder() -> TestReportTree child) {+      \ output.append("---")+      \ child.writeTo(output)+    }+  }+}++define Format {+  autoFormat (value) {+    if (`present` value) {+      return String.builder()+          .append("\"")+          .append(`require` value)+          .append("\"")+          .build()+    } else {+      return "empty"+    }+  }+}
+ lib/testing/test/check-float.0rt view
@@ -0,0 +1,106 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "CheckFloat success" {+  success TestChecker+}++unittest almostEquals {+  \ 1.230000000001 `Matches:with` CheckFloat:almostEquals(1.23)+  \ 1.229999999999 `Matches:with` CheckFloat:almostEquals(1.23)+  \ -1.230000000001 `Matches:with` CheckFloat:almostEquals(-1.23)+  \ -1.229999999999 `Matches:with` CheckFloat:almostEquals(-1.23)+  \ 1000000001.0 `Matches:with` CheckFloat:almostEquals(1000000002.0)+}++unittest closeTo {+  \ 1.24 `Matches:with` CheckFloat:closeTo(1.23, epsilon: 0.011)+  \ 1.22 `Matches:with` CheckFloat:closeTo(1.23, epsilon: 0.011)+  \ -1.24 `Matches:with` CheckFloat:closeTo(-1.23, epsilon: 0.011)+  \ -1.22 `Matches:with` CheckFloat:closeTo(-1.23, epsilon: 0.011)+}+++testcase "CheckFloat:almostEquals failure empty" {+  failure TestChecker+  require "empty .+1.23"+}++unittest test {+  \ empty `Matches:with` CheckFloat:almostEquals(1.23)+}+++testcase "CheckFloat:almostEquals failure above" {+  failure TestChecker+  require "1.24.+ 1.23"+}++unittest test {+  \ 1.24 `Matches:with` CheckFloat:almostEquals(1.23)+}+++testcase "CheckFloat:almostEquals failure expect 0" {+  failure TestChecker+  require "not within"+}++unittest test {+  \ 0.000000001 `Matches:with` CheckFloat:almostEquals(0.0)+}+++testcase "CheckFloat:almostEquals failure below" {+  failure TestChecker+  require "1.22.+ 1.23"+}++unittest test {+  \ 1.22 `Matches:with` CheckFloat:almostEquals(1.23)+}+++testcase "CheckFloat:closeTo failure empty" {+  failure TestChecker+  require "empty .+0.001 .+1.23"+}++unittest test {+  \ empty `Matches:with` CheckFloat:closeTo(1.23, epsilon: 0.001)+}+++testcase "CheckFloat:closeTo failure above" {+  failure TestChecker+  require "1.24.+ 0.001.+ 1.23"+}++unittest test {+  \ 1.24 `Matches:with` CheckFloat:closeTo(1.23, epsilon: 0.001)+}+++testcase "CheckFloat:closeTo failure below" {+  failure TestChecker+  require "1.22.+ 0.001.+ 1.23"+}++unittest test {+  \ 1.22 `Matches:with` CheckFloat:closeTo(1.23, epsilon: 0.001)+}
+ lib/testing/test/check-sequence.0rt view
@@ -0,0 +1,203 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "CheckSequence:equals success" {+  success TestChecker+}++unittest equals {+  ValueList<Int> actual <- ValueList<Int>.new().append(10).append(20).append(30)+  ValueList<Int> expected <- ValueList<Int>.new().append(10).append(20).append(30)+  \ actual `Matches:with` CheckSequence:equals(expected)+}++unittest equalsWithEmpty {+  ValueList<Int> expected <- ValueList<Int>.new()+  \ empty `Matches:with` CheckSequence:equals(expected)+}+++testcase "CheckSequence:equals different" {+  failure TestChecker+  require "10.+40"+  require "20.+50"+  require "30.+60"+}++unittest test {+  ValueList<Int> actual <- ValueList<Int>.new().append(10).append(20).append(30)+  ValueList<Int> expected <- ValueList<Int>.new().append(40).append(50).append(60)+  \ actual `Matches:with` CheckSequence:equals(expected)+}+++testcase "CheckSequence:equals extra" {+  failure TestChecker+  require "40.+unexpected"+}++unittest test {+  ValueList<Int> actual <- ValueList<Int>.new().append(10).append(20).append(30).append(40)+  ValueList<Int> expected <- ValueList<Int>.new().append(10).append(20).append(30)+  \ actual `Matches:with` CheckSequence:equals(expected)+}+++testcase "CheckSequence:equals missing" {+  failure TestChecker+  require "40.+missing"+}++unittest test {+  ValueList<Int> actual <- ValueList<Int>.new().append(10).append(20).append(30)+  ValueList<Int> expected <- ValueList<Int>.new().append(10).append(20).append(30).append(40)+  \ actual `Matches:with` CheckSequence:equals(expected)+}+++testcase "CheckSequence:matches success" {+  success TestChecker+}++unittest matches {+  ValueList<Int> actual <- ValueList<Int>.new().append(1).append(2).append(3)+  ValueList<ValueMatcher<Int>> expected <- ValueList<ValueMatcher<Int>>.new()+      .append(`CheckValue:equals` 1)+      .append(`CheckValue:equals` 2)+      .append(`CheckValue:equals` 3)+  \ actual `Matches:with` CheckSequence:matches(expected)+}++unittest matchesWithEmpty {+  ValueList<ValueMatcher<Int>> expected <- ValueList<ValueMatcher<Int>>.new()+  \ empty `Matches:with` CheckSequence:matches(expected)+}+++testcase "CheckSequence:matches different" {+  failure TestChecker+  require "10.+40"+  require "20.+50"+  require "30.+60"+}++unittest test {+  ValueList<Int> actual <- ValueList<Int>.new().append(10).append(20).append(30)+  ValueList<ValueMatcher<Int>> expected <- ValueList<ValueMatcher<Int>>.new()+      .append(`CheckValue:equals` 40)+      .append(`CheckValue:equals` 50)+      .append(`CheckValue:equals` 60)+  \ actual `Matches:with` CheckSequence:matches(expected)+}+++testcase "CheckSequence:matches extra" {+  failure TestChecker+  require "unexpected"+  require "[Ii]tem #3"+  exclude "[Ii]tem #0"+  exclude "[Ii]tem #1"+  exclude "[Ii]tem #2"+}++unittest test {+  ValueList<Int> actual <- ValueList<Int>.new().append(10).append(20).append(30).append(40)+  ValueList<ValueMatcher<Int>> expected <- ValueList<ValueMatcher<Int>>.new()+      .append(`CheckValue:equals` 10)+      .append(`CheckValue:equals` 20)+      .append(`CheckValue:equals` 30)+  \ actual `Matches:with` CheckSequence:matches(expected)+}+++testcase "CheckSequence:matches missing" {+  failure TestChecker+  require "missing"+  require "[Ii]tem #3"+  exclude "[Ii]tem #0"+  exclude "[Ii]tem #1"+  exclude "[Ii]tem #2"+}++unittest test {+  ValueList<Int> actual <- ValueList<Int>.new().append(10).append(20).append(30)+  ValueList<ValueMatcher<Int>> expected <- ValueList<ValueMatcher<Int>>.new()+      .append(`CheckValue:equals` 10)+      .append(`CheckValue:equals` 20)+      .append(`CheckValue:equals` 30)+      .append(`CheckValue:equals` 40)+  \ actual `Matches:with` CheckSequence:matches(expected)+}+++testcase "CheckSequence:allMatch success" {+  success TestChecker+}++unittest allMatch {+  ValueList<Int> actual <- ValueList<Int>.new().append(1).append(2).append(3)+  \ actual `Matches:with` CheckSequence:allMatch(CheckValue:greaterThanEquals(0))+}++unittest allMatchWithEmpty {+  \ empty `Matches:with` CheckSequence:allMatch(CheckValue:greaterThanEquals(0))+}+++testcase "CheckSequence:allMatch failure" {+  failure TestChecker+  require "10.+25"+  require "20.+25"+  exclude "30.+25"+}++unittest test {+  ValueList<Int> actual <- ValueList<Int>.new().append(10).append(20).append(30)+  \ actual `Matches:with` CheckSequence:allMatch(CheckValue:greaterThanEquals(25))+}+++testcase "CheckSequence:using success" {+  success TestChecker+}++unittest test {+  ValueList<TestValue> actual <- ValueList<TestValue>.new()+      .append(TestValue.default())+      .append(TestValue.new(456, "something", empty))+  ValueList<TestValue> expected <- ValueList<TestValue>.new()+      .append(TestValue.default())+      .append(TestValue.new(456, "something", empty))+  \ actual `Matches:with` CheckSequence:matches(CheckSequence:using(expected))+}+++testcase "CheckSequence:using failure" {+  failure TestChecker+  require "456.+321"+}++unittest test {+  ValueList<TestValue> actual <- ValueList<TestValue>.new()+      .append(TestValue.default())+      .append(TestValue.new(456, "something", empty))+  ValueList<TestValue> expected <- ValueList<TestValue>.new()+      .append(TestValue.default())+      .append(TestValue.new(321, "something", empty))+  \ actual `Matches:with` CheckSequence:matches(CheckSequence:using(expected))+}
+ lib/testing/test/check-string.0rt view
@@ -0,0 +1,162 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "CheckString:contains success" {+  success TestChecker+}++unittest entireString {+  \ "1234567890" `Matches:with` CheckString:contains("1234567890")+}++unittest beginning {+  \ "1234567890" `Matches:with` CheckString:contains("12345")+}++unittest end {+  \ "1234567890" `Matches:with` CheckString:contains("67890")+}++unittest middle {+  \ "1234567890" `Matches:with` CheckString:contains("4567")+}+++testcase "CheckString:contains failure empty" {+  failure TestChecker+  require "does not contain"+  require "empty"+}++unittest test {+  \ empty `Matches:with` CheckString:contains("567890")+}+++testcase "CheckString:contains failure partial" {+  failure TestChecker+  require "does not contain"+  require "567890"+}++unittest test {+  \ "123456789" `Matches:with` CheckString:contains("567890")+}+++testcase "CheckString:contains failure too long" {+  failure TestChecker+  require "does not contain"+  require "123"+}++unittest test {+  \ "123" `Matches:with` CheckString:contains("12345")+}+++testcase "CheckString:startsWith success" {+  success TestChecker+}++unittest entireString {+  \ "1234567890" `Matches:with` CheckString:startsWith("1234567890")+}++unittest beginning {+  \ "1234567890" `Matches:with` CheckString:startsWith("12345")+}+++testcase "CheckString:startsWith failure empty" {+  failure TestChecker+  require "does not start with"+  require "empty"+}++unittest test {+  \ empty `Matches:with` CheckString:startsWith("567890")+}+++testcase "CheckString:startsWith failure not at start" {+  failure TestChecker+  require "does not start with"+  require "567890"+}++unittest test {+  \ "1234567890" `Matches:with` CheckString:startsWith("567890")+}+++testcase "CheckString:startsWith failure too long" {+  failure TestChecker+  require "does not start with"+  require "123"+}++unittest test {+  \ "123" `Matches:with` CheckString:startsWith("12345")+}+++testcase "CheckString:endsWith success" {+  success TestChecker+}++unittest entireString {+  \ "1234567890" `Matches:with` CheckString:endsWith("1234567890")+}++unittest end {+  \ "1234567890" `Matches:with` CheckString:endsWith("567890")+}+++testcase "CheckString:endsWith failure empty" {+  failure TestChecker+  require "does not end with"+  require "empty"+}++unittest test {+  \ empty `Matches:with` CheckString:endsWith("567890")+}+++testcase "CheckString:endsWith failure not at end" {+  failure TestChecker+  require "does not end with"+  require "123456"+}++unittest test {+  \ "1234567890" `Matches:with` CheckString:endsWith("123456")+}+++testcase "CheckString:endsWith failure too long" {+  failure TestChecker+  require "does not end with"+  require "345"+}++unittest test {+  \ "345" `Matches:with` CheckString:endsWith("12345")+}
+ lib/testing/test/check-value.0rt view
@@ -0,0 +1,409 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "CheckValue:equals success" {+  success TestChecker+}++unittest nonEmpty {+  \ "foo" `Matches:with` CheckValue:equals("foo")+}++unittest bothEmpty {+  \ empty?String `Matches:with` CheckValue:equals(empty?String)+}+++testcase "CheckValue:equals failure not equal" {+  failure TestChecker+  require "foo"+  require "bar"+}++unittest test {+  \ "foo" `Matches:with` CheckValue:equals("bar")+}+++testcase "CheckValue:equals failure left empty" {+  failure TestChecker+  require "empty"+  require "bar"+}++unittest test {+  \ empty?String `Matches:with` CheckValue:equals("bar")+}+++testcase "CheckValue:equals failure right empty" {+  failure TestChecker+  require "foo"+  require "empty"+}++unittest test {+  \ "foo" `Matches:with` CheckValue:equals(empty?String)+}+++testcase "CheckValue:notEquals success" {+  success TestChecker+}++unittest nonEmpty {+  \ "foo" `Matches:with` CheckValue:notEquals("bar")+}++unittest leftEmpty {+  \ empty?String `Matches:with` CheckValue:notEquals("bar")+}++unittest rightEmpty {+  \ "foo" `Matches:with` CheckValue:notEquals(empty?String)+}+++testcase "CheckValue:notEquals failure non-empty" {+  failure TestChecker+  require "foo"+}++unittest test {+  \ "foo" `Matches:with` CheckValue:notEquals("foo")+}+++testcase "CheckValue:notEquals failure empty" {+  failure TestChecker+  require "empty"+}++unittest test {+  \ empty?String `Matches:with` CheckValue:notEquals(empty?String)+}+++testcase "CheckValue:is success" {+  success TestChecker+}++unittest test {+  String value <- "foo"+  \ value `Matches:with` CheckValue:is(value)+}+++testcase "CheckValue:is failure same value" {+  failure TestChecker+  require "String@[a-f0-9]+"+  exclude "foo"+}++unittest test {+  \ "foo" `Matches:with` CheckValue:is("foo")+}+++testcase "CheckValue:using success" {+  success TestChecker+}++unittest test {+  \ TestValue.default() `Matches:with` `CheckValue:using` TestValue.default()+}+++testcase "CheckValue:using failure not equal" {+  failure TestChecker+  require "message1"+}++unittest test {+  \ TestValue.default() `Matches:with` `CheckValue:using` TestValue.new(123, "message1", empty)+}+++testcase "CheckValue:using failure left empty" {+  failure TestChecker+  require "empty"+}++unittest test {+  \ empty?TestValue `Matches:with` `CheckValue:using` TestValue.new(123, "message1", empty)+}+++testcase "CheckValue:lessThanNotEqual success" {+  success TestChecker+}++unittest test {+  \ 0 `Matches:with` CheckValue:lessThanNotEquals(1)+}+++testcase "CheckValue:lessThanNotEqual failure non-empty" {+  failure TestChecker+  require "100"+  require "20"+}++unittest test {+  \ 100 `Matches:with` CheckValue:lessThanNotEquals(20)+}+++testcase "CheckValue:lessThanNotEqual failure endpoint" {+  failure TestChecker+  require "100"+}++unittest test {+  \ 100 `Matches:with` CheckValue:lessThanNotEquals(100)+}+++testcase "CheckValue:lessThanNotEqual failure empty" {+  failure TestChecker+  require "empty"+  require "20"+}++unittest test {+  \ empty?Int `Matches:with` CheckValue:lessThanNotEquals(20)+}+++testcase "CheckValue:greaterThanNotEqual success" {+  success TestChecker+}++unittest test {+  \ 1 `Matches:with` CheckValue:greaterThanNotEquals(0)+}+++testcase "CheckValue:greaterThanNotEqual failure non-empty" {+  failure TestChecker+  require "10"+  require "200"+}++unittest test {+  \ 10 `Matches:with` CheckValue:greaterThanNotEquals(200)+}+++testcase "CheckValue:greaterThanNotEqual failure endpoint" {+  failure TestChecker+  require "10"+}++unittest test {+  \ 10 `Matches:with` CheckValue:greaterThanNotEquals(10)+}+++testcase "CheckValue:greaterThanNotEqual failure empty" {+  failure TestChecker+  require "empty"+  require "20"+}++unittest test {+  \ empty?Int `Matches:with` CheckValue:greaterThanNotEquals(20)+}+++testcase "CheckValue:betweenNotEqual success" {+  success TestChecker+}++unittest test {+  \ 1 `Matches:with` CheckValue:betweenNotEquals(0, 3)+}+++testcase "CheckValue:betweenNotEqual failure below" {+  failure TestChecker+  require "3"+  require "5"+  require "200"+}++unittest test {+  \ 3 `Matches:with` CheckValue:betweenNotEquals(5, 200)+}+++testcase "CheckValue:betweenNotEqual failure above" {+  failure TestChecker+  require "300"+  require "5"+  require "200"+}++unittest test {+  \ 300 `Matches:with` CheckValue:betweenNotEquals(5, 200)+}+++testcase "CheckValue:betweenNotEqual failure endpoint low" {+  failure TestChecker+  require "5"+  require "200"+}++unittest test {+  \ 5 `Matches:with` CheckValue:betweenNotEquals(5, 200)+}+++testcase "CheckValue:betweenNotEqual failure endpoint high" {+  failure TestChecker+  require "5"+  require "200"+}++unittest test {+  \ 200 `Matches:with` CheckValue:betweenNotEquals(5, 200)+}+++testcase "CheckValue:betweenNotEqual failure empty" {+  failure TestChecker+  require "empty"+  require "5"+  require "200"+}++unittest test {+  \ empty?Int `Matches:with` CheckValue:betweenNotEquals(5, 200)+}+++testcase "CheckValue:lessThanEqual success" {+  success TestChecker+}++unittest test {+  \ 0 `Matches:with` CheckValue:lessThanEquals(1)+  \ 0 `Matches:with` CheckValue:lessThanEquals(0)+}+++testcase "CheckValue:lessThanEqual failure non-empty" {+  failure TestChecker+  require "100"+  require "20"+}++unittest test {+  \ 100 `Matches:with` CheckValue:lessThanEquals(20)+}+++testcase "CheckValue:lessThanEqual failure empty" {+  failure TestChecker+  require "empty"+  require "20"+}++unittest test {+  \ empty?Int `Matches:with` CheckValue:lessThanEquals(20)+}+++testcase "CheckValue:greaterThanEqual success" {+  success TestChecker+}++unittest test {+  \ 1 `Matches:with` CheckValue:greaterThanEquals(0)+  \ 1 `Matches:with` CheckValue:greaterThanEquals(1)+}+++testcase "CheckValue:greaterThanEqual failure non-empty" {+  failure TestChecker+  require "10"+  require "200"+}++unittest test {+  \ 10 `Matches:with` CheckValue:greaterThanEquals(200)+}+++testcase "CheckValue:greaterThanEqual failure empty" {+  failure TestChecker+  require "empty"+  require "20"+}++unittest test {+  \ empty?Int `Matches:with` CheckValue:greaterThanEquals(20)+}+++testcase "CheckValue:betweenEqual success" {+  success TestChecker+}++unittest test {+  \ 1 `Matches:with` CheckValue:betweenEquals(0, 3)+  \ 0 `Matches:with` CheckValue:betweenEquals(0, 3)+  \ 3 `Matches:with` CheckValue:betweenEquals(0, 3)+}+++testcase "CheckValue:betweenEqual failure below" {+  failure TestChecker+  require "3"+  require "5"+  require "200"+}++unittest test {+  \ 3 `Matches:with` CheckValue:betweenEquals(5, 200)+}+++testcase "CheckValue:betweenEqual failure above" {+  failure TestChecker+  require "300"+  require "5"+  require "200"+}++unittest test {+  \ 300 `Matches:with` CheckValue:betweenEquals(5, 200)+}+++testcase "CheckValue:betweenEqual failure empty" {+  failure TestChecker+  require "empty"+  require "5"+  require "200"+}++unittest test {+  \ empty?Int `Matches:with` CheckValue:betweenEquals(5, 200)+}
+ lib/testing/test/checker.0rt view
@@ -0,0 +1,154 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "TestChecker.isFailing fails if not started" {+  failure+  require "not started"+}++unittest test {+  \ TestChecker.isFailing()+}+++testcase "TestChecker.finish fails if not started" {+  failure+  require "not started"+}++unittest test {+  \ TestChecker.finish()+}+++testcase "TestChecker.checkNow fails if not started" {+  failure+  require "not started"+}++unittest test {+  \ TestChecker.checkNow()+}+++testcase "TestChecker.start fails if already started" {+  failure+  require "already started"+}++unittest test {+  \ TestChecker.start()+  \ TestChecker.start()+}+++testcase "TestChecker.newReport fails if not started" {+  failure+  require "not started"+}++unittest test {+  \ TestChecker.newReport(title: "title", context: empty)+}+++testcase "TestChecker explicit start and finish" {+  success+}++unittest test {+  \ TestChecker.start()+  \ TestChecker.newReport(title: "title", context: empty)+  \ TestChecker.newReport(title: "title", context: empty).newSection(title: "subtitle")+  \ Testing.checkEquals(TestChecker.isFailing(), false)+  \ TestChecker.checkNow()+  \ TestChecker.finish()+}+++testcase "TestChecker succeeds by default" {+  success TestChecker+}++unittest test { }+++testcase "TestChecker fails when error added to report" {+  failure TestChecker+  require "context1"+  require "context2"+  require "title1"+  require "message1"+  require "title2"+  require "message2"+  exclude "testError"+}++unittest testError {+  ValueList<String> context <- ValueList<String>.new()+      .append("context1")+      .append("context2")+  \ TestChecker.newReport(title: "title1", context: context.defaultOrder()).addError(message: "message1")+  \ TestChecker.newReport(title: "title2", context: empty).addError(message: "message2")+}+++testcase "TestChecker fails when error added to child" {+  failure TestChecker+  require "title"+  require "child"+  require "message"+  exclude "testError"+}++unittest testError {+  TestReport report <- TestChecker.newReport(title: "title", context: empty)+  TestReport child <- report.newSection(title: "child")+  \ child.addError(message: "message")+}+++testcase "TestChecker ignores discarded errors" {+  success TestChecker+}++unittest topLevel {+  TestReport report <- TestChecker.newReport(title: "title", context: empty)+  \ Testing.checkEquals(report.hasError(), false)++  \ report.addError(message: "message")+  \ Testing.checkEquals(report.hasError(), true)++  \ report.discardReport()+  \ Testing.checkEquals(report.hasError(), false)+}++unittest recursive {+  TestReport report <- TestChecker.newReport(title: "title", context: empty)+  TestReport child <- report.newSection(title: "child")+  \ Testing.checkEquals(report.hasError(), false)+  \ Testing.checkEquals(child.hasError(), false)++  \ child.addError(message: "message")+  \ Testing.checkEquals(report.hasError(), true)+  \ Testing.checkEquals(child.hasError(), true)++  \ report.discardReport()+  \ Testing.checkEquals(report.hasError(), false)+  \ Testing.checkEquals(child.hasError(), true)+}
+ lib/testing/test/evaluation.0rt view
@@ -0,0 +1,184 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "Matches no errors" {+  success TestChecker+}++unittest withOnce {+  \ "foo" `Matches:with` CheckAlways:match()+}++unittest withMulti {+  \ "foo" `Matches:with` CheckAlways:match()+  \ "foo" `Matches:with` CheckAlways:match()+}++unittest tryWithOnce {+  \ "foo" `Matches:tryWith` CheckAlways:match()+}++unittest tryWithMulti {+  \ "foo" `Matches:tryWith` CheckAlways:match()+  \ "foo" `Matches:tryWith` CheckAlways:match()+}++unittest valueOnce {+  \ TestValue.default() `Matches:value` TestValue.default()+}++unittest valueMulti {+  \ TestValue.default() `Matches:value` TestValue.default()+  \ TestValue.default() `Matches:value` TestValue.default()+}++unittest tryValueOnce {+  \ TestValue.default() `Matches:tryValue` TestValue.default()+}++unittest tryValueMulti {+  \ TestValue.default() `Matches:tryValue` TestValue.default()+  \ TestValue.default() `Matches:tryValue` TestValue.default()+}+++testcase "Matches:with fails immediately" {+  failure TestChecker+  require "message1"+  exclude "message2"+}++unittest test {+  \ "foo" `Matches:with` CheckAlways:error("message1")+  \ "foo" `Matches:with` CheckAlways:error("message2")+}+++testcase "Matches:tryWith fails later" {+  failure TestChecker+  require "message1"+  require "message2"+}++unittest test {+  \ "foo" `Matches:tryWith` CheckAlways:error("message1")+  \ "foo" `Matches:tryWith` CheckAlways:error("message2")+}+++testcase "Matches:value fails immediately" {+  failure TestChecker+  require "message1"+  exclude "321"+  exclude "message2"+  exclude "999"+}++unittest test {+  \ TestValue.default() `Matches:value` TestValue.new(123, "message1", empty)+  \ TestValue.default() `Matches:value` TestValue.new(321, "message2", 999)+}+++testcase "Matches:value failure with empty" {+  failure TestChecker+  require "empty"+}++unittest test {+  \ empty?TestValue `Matches:value` TestValue.new(123, "message1", empty)+}+++testcase "Matches:tryValue fails later" {+  failure TestChecker+  require "message1"+  require "321"+  require "message2"+  require "999"+}++unittest test {+  \ TestValue.default() `Matches:tryValue` TestValue.new(123, "message1", empty)+  \ TestValue.default() `Matches:tryValue` TestValue.new(321, "message2", 999)+}+++testcase "Matches:tryValue failure with empty" {+  failure TestChecker+  require "empty"+}++unittest test {+  \ empty?TestValue `Matches:tryValue` TestValue.new(123, "message1", empty)+}+++testcase "Matches:with doesn't evaluate pending errors" {+  failure TestChecker+  require "message2"+  exclude "message1"+}++unittest test {+  \ "foo" `Matches:tryWith` CheckAlways:error("message1")+  \ "foo" `Matches:with` CheckAlways:match()+  fail("message2")+}+++testcase "Matches:value doesn't evaluate pending errors" {+  failure TestChecker+  require "message2"+  exclude "message1"+}++unittest test {+  \ TestValue.default() `Matches:tryValue` TestValue.new(123, "message1", empty)+  \ TestValue.default() `Matches:value` TestValue.default()+  fail("message2")+}+++testcase "CheckAlways" {+  success+}++unittest match {+  TestReportTree report <- TestReportTree.new("title", ValueList<Formatted>.new())+  \ CheckAlways:match().check(123, report)+  \ Testing.checkEquals(report.hasError(), false)+}++unittest fromWithoutError {+  TestReportTree report <- TestReportTree.new("title", ValueList<Formatted>.new())+  \ CheckAlways:error("message").check(123, report)+  \ Testing.checkEquals(report.hasError(), true)+}+++testcase "CheckAlways:die" {+  failure+  require "something"+}++unittest test {+  TestReportTree report <- TestReportTree.new("title", ValueList<Formatted>.new())+  \ report.addError(message: "message")+  \ CheckAlways:die("something").check(123, report)+}
+ lib/testing/test/helpers.0rp view
@@ -0,0 +1,35 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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]++$ModuleOnly$+$TestsOnly$++concrete TestValue {+  refines TestCompare<TestValue>+  // TestValue.new(123, "message", empty)+  defines Default++  @type new (Int, String, optional Int) -> (#self)+}++concrete Testing {+  @type checkEquals<#x>+    #x requires Formatted+    #x defines Equals<#x>+  (optional #x, optional #x) -> ()+}
+ lib/testing/test/helpers.0rx view
@@ -0,0 +1,69 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 TestValue {+  $ReadOnlyExcept[]$++  @value Int number+  @value String message+  @value optional Int error++  new (number, message, error) {+    return delegate -> #self+  }++  default () {+    return new(123, "message", empty)+  }++  testCompare (actual, report) {+    \ MultiChecker.new(report)+        .tryCheck(title: "number", actual.number(), CheckValue:equals(number))+        .tryCheck(title: "message", actual.message(), CheckValue:equals(message))+        .tryCheck(title: "error", actual.error(), CheckValue:equals(error))+  }++  @value number () -> (Int)+  number () { return number }++  @value message () -> (String)+  message () { return message }++  @value error () -> (optional Int)+  error () { return error }+}++define Testing {+  checkEquals (x, y) { $NoTrace$+    Bool failed <- false+    if (`present` x && `present` y && !#x.equals(`require` x, `require` y)) {+      failed <- true+    } elif (`present` x != `present` y) {+      failed <- true+    }+    if (failed) {+      fail(String.builder()+          .append(`Format:autoFormat` x)+          .append(" is not equal to ")+          .append(`Format:autoFormat` y)+          .build())+    }+  }+}
+ lib/testing/test/matching.0rt view
@@ -0,0 +1,218 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "MultiChecker.check short cicuits" {+  failure+  require "title0"+  require "title2"+  require "message2"+  exclude "title1"+  exclude "title3"+  exclude "message3"+}++unittest test {+  TestReportTree report <- TestReportTree.new("title0", ValueList<Formatted>.new())++  \ MultiChecker.new(report)+      .check(title: "title1", "foo", CheckAlways:match())+      &.check(title: "title2", "foo", CheckAlways:error("message2"))+      &.check(title: "title3", "foo", CheckAlways:error("message3"))++  IndentAppend output <- IndentAppend.new(String.builder())+  \ report.prune()&.writeTo(output)+  \ TestHandler:failAndExit(output.build().formatted())+}+++testcase "MultiChecker.tryCheck continues" {+  failure+  require "title0"+  require "title2"+  require "message2"+  require "title3"+  require "message3"+  exclude "title1"+}++unittest test {+  TestReportTree report <- TestReportTree.new("title0", ValueList<Formatted>.new())++  \ MultiChecker.new(report)+      .tryCheck<String>(title: "title1", "foo", CheckAlways:match())+      .tryCheck<String>(title: "title2", "foo", CheckAlways:error("message2"))+      .tryCheck<String>(title: "title3", "foo", CheckAlways:error("message3"))++  IndentAppend output <- IndentAppend.new(String.builder())+  \ report.prune()&.writeTo(output)+  \ TestHandler:failAndExit(output.build().formatted())+}+++testcase "MultiChecker.check doesn't force pending errors" {+  failure+  require "title0"+  require "title1"+  require "message1"+  require "title3"+  require "message3"+  exclude "title2"+}++unittest test {+  TestReportTree report <- TestReportTree.new("title0", ValueList<Formatted>.new())++  \ MultiChecker.new(report)+      .tryCheck<String>(title: "title1", "foo", CheckAlways:error("message1"))+      .check(title: "title2", "foo", CheckAlways:match())+      &.tryCheck<String>(title: "title3", "foo", CheckAlways:error("message3"))++  IndentAppend output <- IndentAppend.new(String.builder())+  \ report.prune()&.writeTo(output)+  \ TestHandler:failAndExit(output.build().formatted())+}+++testcase "MatcherCompose:not success" {+  success TestChecker+}++unittest test {+  \ "foo" `Matches:with` `MatcherCompose:not` CheckAlways:error("message")+}+++testcase "MatcherCompose:not failure" {+  failure TestChecker+  require "expected failure"+}++unittest test {+  \ "foo" `Matches:with` `MatcherCompose:not` CheckAlways:match()+}+++testcase "MatcherCompose:or success" {+  success TestChecker+}++unittest test {+  \ "foo" `Matches:with` (CheckAlways:match() `MatcherCompose:or` CheckAlways:match())+  \ "foo" `Matches:with` (CheckAlways:match() `MatcherCompose:or` CheckAlways:error("message"))+  \ "foo" `Matches:with` (CheckAlways:error("message") `MatcherCompose:or` CheckAlways:match())+}+++testcase "MatcherCompose:or failure" {+  failure TestChecker+  require "message1"+  require "message2"+}++unittest test {+  \ "foo" `Matches:with` (CheckAlways:error("message1") `MatcherCompose:or` CheckAlways:error("message2"))+}+++testcase "MatcherCompose:and success" {+  success TestChecker+}++unittest test {+  \ "foo" `Matches:with` (CheckAlways:match() `MatcherCompose:and` CheckAlways:match())+}+++testcase "MatcherCompose:and failure both" {+  failure TestChecker+  require "message1"+  require "message2"+}++unittest test {+  \ "foo" `Matches:with` (CheckAlways:error("message1") `MatcherCompose:and` CheckAlways:error("message2"))+}+++testcase "MatcherCompose:and failure one" {+  failure TestChecker+  require "message"+}++unittest test {+  \ "foo" `Matches:with` (CheckAlways:match() `MatcherCompose:and` CheckAlways:error("message"))+}+++testcase "MatcherCompose:anyOf success" {+  success TestChecker+}++unittest someMatching {+  \ "foo" `Matches:with` MatcherCompose:anyOf(ValueList<ValueMatcher<any>>.new()+      .append(CheckAlways:error("message"))+      .append(CheckAlways:match())+      .append(CheckAlways:die("message")))+}++unittest emptyList {+  \ "foo" `Matches:with` MatcherCompose:anyOf(ValueList<ValueMatcher<any>>.new())+}+++testcase "MatcherCompose:anyOf failure" {+  failure TestChecker+  require "message1"+  require "message2"+}++unittest test {+  \ "foo" `Matches:with` MatcherCompose:anyOf(ValueList<ValueMatcher<any>>.new()+      .append(CheckAlways:error("message1"))+      .append(CheckAlways:error("message2")))+}+++testcase "MatcherCompose:allOf success" {+  success TestChecker+}++unittest allMatching {+  \ "foo" `Matches:with` MatcherCompose:allOf(ValueList<ValueMatcher<any>>.new()+      .append(CheckAlways:match())+      .append(CheckAlways:match()))+}++unittest emptyList {+  \ "foo" `Matches:with` MatcherCompose:allOf(ValueList<ValueMatcher<any>>.new())+}+++testcase "MatcherCompose:allOf failure" {+  failure TestChecker+  require "message1"+  require "message2"+}++unittest test {+  \ "foo" `Matches:with` MatcherCompose:allOf(ValueList<ValueMatcher<any>>.new()+      .append(CheckAlways:match())+      .append(CheckAlways:error("message1"))+      .append(CheckAlways:match())+      .append(CheckAlways:error("message2")))+}
− lib/testing/test/tests.0rt
@@ -1,254 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2020-2021 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 "checkNotEquals success" {-  success-}--unittest test {-  \ Testing.checkNotEquals(12,13)-}---testcase "checkNotEquals fail" {-  crash-  require stderr "13.*13"-}--unittest test {-  \ Testing.checkNotEquals(13,13)-}---testcase "checkEmpty success" {-  success-}--unittest formatted {-  \ Testing.checkEmpty(empty)-}--unittest notFormatted {-  optional CharBuffer value <- empty-  \ Testing.checkEmpty(value)-}---testcase "checkEmpty fail formatted" {-  crash-  require stderr "13"-  require stderr "empty"-}--unittest test {-  \ Testing.checkEmpty(13)-}---testcase "checkEmpty fail unformatted" {-  crash-  require stderr "unformatted"-  require stderr "empty"-}--unittest test {-  CharBuffer value <- CharBuffer.new(10)-  \ Testing.checkEmpty(value)-}---testcase "checkPresent success" {-  success-}--unittest test {-  \ Testing.checkPresent(13)-}---testcase "checkPresent fail" {-  crash-  require stderr "empty"-}--unittest test {-  \ Testing.checkPresent(empty)-}---testcase "checkOptional success" {-  success-}--unittest test {-  \ Testing.checkOptional<Int>(empty,empty)-  \ Testing.checkOptional(13,13)-}---testcase "checkOptional fail empty" {-  crash-  require stderr "13"-  require stderr "empty"-}--unittest test {-  \ Testing.checkOptional(13,empty)-}---testcase "checkOptional fail present" {-  crash-  require stderr "13"-  require stderr "empty"-}--unittest test {-  \ Testing.checkOptional(empty,13)-}---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)-}---testcase "checkGreaterThan success" {-  success-}--unittest test {-  \ Testing.checkGreaterThan(13,11)-}---testcase "checkGreaterThan fail" {-  crash-  require stderr "13"-  require stderr "14"-}--unittest test {-  \ Testing.checkGreaterThan(13,14)-}---testcase "checkLessThan success" {-  success-}--unittest test {-  \ Testing.checkLessThan(13,14)-}---testcase "checkLessThan fail" {-  crash-  require stderr "13"-  require stderr "11"-}--unittest test {-  \ Testing.checkLessThan(13,11)-}---testcase "checkTrue success" {-  success-}--unittest test {-  \ Testing.checkTrue(1)-}---testcase "checkTrue fail" {-  crash-  require stderr "true"-}--unittest test {-  \ Testing.checkTrue(0)-}---testcase "checkFalse success" {-  success-}--unittest test {-  \ Testing.checkFalse(0)-}---testcase "checkFalse fail" {-  crash-  require stderr "false"-}--unittest test {-  \ Testing.checkFalse(1)-}
+ lib/testing/test/util.0rt view
@@ -0,0 +1,195 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "IndentAppend" {+  success+}++unittest nothingAppended {+  String result <- IndentAppend.new(String.builder())+      .build()+      .formatted()+  \ Testing.checkEquals(result, "")+}++unittest addNewline {+  String result <- IndentAppend.new(String.builder())+      .addNewline()+      .build()+      .formatted()+  \ Testing.checkEquals(result, "\n")+}++unittest usesNewlines {+  String result <- IndentAppend.new(String.builder())+      .append("message1")+      .append("message2")+      .build()+      .formatted()+  \ Testing.checkEquals(result, "message1\nmessage2\n")+}++unittest indents {+  String result <- IndentAppend.new(String.builder())+      .pushIndent()+      .append("message1")+      .pushIndent()+      .append("message2")+      .popIndent()+      .popIndent()+      .append("message3")+      .build()+      .formatted()+  \ Testing.checkEquals(result, "  message1\n    message2\nmessage3\n")+}+++testcase "ValueList" {+  success+}++concrete Helper {+  @type new (ValueList<Int>) -> (Helper)++  @value checkNext (Int) -> (Helper)+  @value checkFinished () -> ()+}++define Helper {+  @value optional Order<Int> current++  new (list) {+    return Helper{ list.defaultOrder() }+  }++  checkNext (value) {+    \ Testing.checkEquals(current&.get(), value)+    current <- current&.next()+    return self+  }++  checkFinished () {+    if (`present` current) {+      fail("list not empty")+    }+  }+}++unittest nothingAdded {+  ValueList<Int> list <- ValueList<Int>.new()+  \ Testing.checkEquals(list.isEmpty(), true)+  \ Helper.new(list)+      .checkFinished()+}++unittest withItems {+  ValueList<Int> list <- ValueList<Int>.new()+      .append(1)+      .append(2)+      .append(3)+  \ Testing.checkEquals(list.isEmpty(), false)+  \ Helper.new(list)+      .checkNext(1)+      .checkNext(2)+      .checkNext(3)+      .checkFinished()+}+++testcase "TestHandler skips tracing" {+  failure+  require "message"+  exclude "exitTest"+}++unittest exitTest {+  \ TestHandler:failAndExit("message")+}+++testcase "TestReportTree success" {+  success+}++unittest nothingAdded {+  TestReportTree report <- TestReportTree.new("title", ValueList<Formatted>.new())+  IndentAppend output <- IndentAppend.new(String.builder())+  \ Testing.checkEquals(report.hasError(), false)+  \ report.prune()&.writeTo(output)+  \ Testing.checkEquals(output.build().formatted(), "")+}++unittest nonFailingSections {+  TestReportTree report <- TestReportTree.new("title", ValueList<Formatted>.new())+  \ report.newSection(title: "child1")+  \ report.newSection(title: "child2")+  \ Testing.checkEquals(report.hasError(), false)+  IndentAppend output <- IndentAppend.new(String.builder())+  \ report.prune()&.writeTo(output)+  \ Testing.checkEquals(output.build().formatted(), "")+}+++testcase "TestReportTree prune doesn't include non-failing sections" {+  failure+  require "title"+  require "child2"+  require "message2"+  require "child4"+  require "message4"+  exclude "child1"+  exclude "child5"+}++unittest test {+  TestReportTree report <- TestReportTree.new("title", ValueList<Formatted>.new())+  \ report.newSection(title: "child1")+  \ report.newSection(title: "child2").addError(message: "message2")+  \ report.newSection(title: "child3").addError(message: "message3").discardReport()+  \ report.newSection(title: "child4").addError(message: "message4")+  \ report.newSection(title: "child5")+  \ Testing.checkEquals(report.hasError(), true)+  IndentAppend output <- IndentAppend.new(String.builder())+  \ report.prune()&.writeTo(output)+  \ TestHandler:failAndExit(output.build().formatted())+}+++testcase "TestReportTree unpruned preserves non-failing sections" {+  failure+  require "title"+  require "child1"+  require "child2"+  require "message2"+  require "child4"+  require "message4"+  require "child5"+}++unittest test {+  TestReportTree report <- TestReportTree.new("title", ValueList<Formatted>.new())+  \ report.newSection(title: "child1")+  \ report.newSection(title: "child2").addError(message: "message2")+  \ report.newSection(title: "child3").addError(message: "message3").discardReport()+  \ report.newSection(title: "child4").addError(message: "message4")+  \ report.newSection(title: "child5")+  \ Testing.checkEquals(report.hasError(), true)+  IndentAppend output <- IndentAppend.new(String.builder())+  \ report.writeTo(output)+  \ TestHandler:failAndExit(output.build().formatted())+}
lib/thread/.zeolite-module view
@@ -24,6 +24,12 @@     categories: [EnumeratedBarrier EnumeratedWait]   } ]+extension_specs: [+  category {+    name: EnumeratedBarrier+    refines: [ReadAt<BarrierWait>]+  }+] mode: incremental {   link_flags: ["-lpthread"] }
lib/thread/barrier.0rp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -16,6 +16,9 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] +// NOTE: This functionality isn't available on MacOS because MacOS doesn't+// support thread barriers.+ // Waits for a thread barrier. @value interface BarrierWait {   // Block until the barrier condition is satisfied.@@ -24,8 +27,6 @@  // A thread barrier validated using thread enumeration. concrete EnumeratedBarrier {-  refines ReadAt<BarrierWait>-   // Create a new barrier for a fixed number of threads.   //   // Args:
lib/thread/src/Extension_Enumerated.cpp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -19,7 +19,10 @@ #include <atomic> #include <vector> +#ifndef __APPLE__ #include <pthread.h>+#endif+ #include <string.h>  #include "category-source.hpp"@@ -29,6 +32,8 @@ #include "Category_EnumeratedBarrier.hpp" #include "Category_Int.hpp" +#ifndef __APPLE__+ namespace {  class Barrier {@@ -97,13 +102,19 @@  }  // namespace +#endif+ #ifdef ZEOLITE_PRIVATE_NAMESPACE namespace ZEOLITE_PRIVATE_NAMESPACE { #endif  // ZEOLITE_PRIVATE_NAMESPACE +#ifndef __APPLE__+ BoxedValue CreateValue_EnumeratedWait(   S<const Type_EnumeratedWait> parent, S<Barrier> b, int i); +#endif+ struct ExtCategory_EnumeratedWait : public Category_EnumeratedWait { }; @@ -111,6 +122,8 @@   inline ExtType_EnumeratedWait(Category_EnumeratedWait& p, Params<0>::Type params) : Type_EnumeratedWait(p, params) {} }; +#ifndef __APPLE__+ struct ExtValue_EnumeratedWait : public Value_EnumeratedWait {   inline ExtValue_EnumeratedWait(S<const Type_EnumeratedWait> p, S<Barrier> b, int i)     : Value_EnumeratedWait(std::move(p)), barrier(b), index(i) {}@@ -129,6 +142,8 @@   int index; }; +#endif+ Category_EnumeratedWait& CreateCategory_EnumeratedWait() {   static auto& category = *new ExtCategory_EnumeratedWait();   return category;@@ -141,11 +156,15 @@  void RemoveType_EnumeratedWait(const Params<0>::Type& params) {} +#ifndef __APPLE__+ BoxedValue CreateValue_EnumeratedWait(   S<const Type_EnumeratedWait> parent, S<Barrier> b, int i) {   return BoxedValue::New<ExtValue_EnumeratedWait>(std::move(parent), std::move(b), i); } +#endif+ #ifdef ZEOLITE_PRIVATE_NAMESPACE }  // namespace ZEOLITE_PRIVATE_NAMESPACE using namespace ZEOLITE_PRIVATE_NAMESPACE;@@ -167,6 +186,9 @@    ReturnTuple Call_new(const ParamsArgs& params_args) const final {     TRACE_FUNCTION("EnumeratedBarrier.new")+#ifdef __APPLE__+    FAIL() << "Error creating barriers: BarrierWait not supported on MacOS";+#else     const PrimInt Var_arg1 = (params_args.GetArg(0)).AsInt();     if (Var_arg1 < 0) {       FAIL() << "Invalid barrier thread count " << Var_arg1;@@ -179,6 +201,7 @@       waits.push_back(wait);     }     return ReturnTuple(CreateValue_EnumeratedBarrier(PARAM_SELF, std::move(waits)));+#endif   } }; 
lib/thread/src/testing.0rx view
@@ -20,15 +20,15 @@  define NoOpRoutine {   create () {-    return NoOpRoutine{ }+    return delegate -> #self   } -  run () {}+  run () { } }  define CrashRoutine {   create () {-    return CrashRoutine{ }+    return delegate -> #self   }    run () {@@ -38,7 +38,7 @@  define InfiniteRoutine {   create () {-    return InfiniteRoutine{ }+    return delegate -> #self   }    run () { $NoTrace$
lib/thread/test/barrier.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,12 +17,12 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "EnumeratedBarrier tests" {-  success+  success TestChecker }  unittest correctCount {   ReadAt<BarrierWait> barriers <- EnumeratedBarrier.new(13)-  \ Testing.checkEquals(barriers.size(),13)+  \ barriers.size() `Matches:with` CheckValue:equals(13) }  unittest waitForOneThread {@@ -32,7 +32,7 @@  unittest zeroAllowed {   ReadAt<BarrierWait> barriers <- EnumeratedBarrier.new(0)-  \ Testing.checkEquals(barriers.size(),0)+  \ barriers.size() `Matches:with` CheckValue:equals(0) }  unittest waitForMultipleThreads {@@ -40,14 +40,14 @@   Mutex mutex <- SimpleMutex.new()   ReadAt<BarrierWait> barriers <- EnumeratedBarrier.new(3) -  Thread thread1 <- ProcessThread.from(WaitAndIncrement.create(2,value,mutex,barriers.readAt(1))).start()-  Thread thread2 <- ProcessThread.from(WaitAndIncrement.create(2,value,mutex,barriers.readAt(2))).start()+  Thread thread1 <- ProcessThread.from(WaitAndIncrement.create(2, value, mutex, barriers.readAt(1))).start()+  Thread thread2 <- ProcessThread.from(WaitAndIncrement.create(2, value, mutex, barriers.readAt(2))).start()    \ barriers.readAt(0).wait()-  \ Testing.checkEquals(value.get(),2)+  \ value.get() `Matches:with` CheckValue:equals(2)    \ barriers.readAt(0).wait()-  \ Testing.checkEquals(value.get(),4)+  \ value.get() `Matches:with` CheckValue:equals(4)    \ thread1.join()   \ thread2.join()@@ -56,7 +56,7 @@ concrete WaitAndIncrement {   refines Routine -  @type create (Int,Value,Mutex,BarrierWait) -> (WaitAndIncrement)+  @type create (Int, Value, Mutex, BarrierWait) -> (WaitAndIncrement) }  define WaitAndIncrement {@@ -65,7 +65,7 @@   @value Mutex mutex   @value BarrierWait barrier -  create (count,value,mutex,barrier) {+  create (count, value, mutex, barrier) {     return WaitAndIncrement{ count, value, mutex, barrier }   } @@ -73,7 +73,7 @@     scoped {       Int i <- 0     } in while (i < count) {-      $Hidden[i,count]$+      $Hidden[i, count]$       scoped {         MutexLock lock <- MutexLock.lock(mutex)       } cleanup {@@ -92,7 +92,7 @@   testcase "EnumeratedBarrier crashes with negative count" {-  crash+  failure   require "-4" } @@ -102,7 +102,7 @@   testcase "wait() crashes when references are lost" {-  crash+  failure   require "BarrierWait.*destroyed" } @@ -115,7 +115,7 @@   testcase "references lost during wait() causes crash" {-  crash+  failure   require "BarrierWait.*waiting" } @@ -149,7 +149,7 @@   testcase "wait() crashes when two threads use same BarrierWait" {-  crash+  failure   require "BarrierWait.*in use" } 
lib/thread/test/condition.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,15 +17,15 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "ThreadCondition tests" {-  success+  success TestChecker }  unittest resumeAll {   Value value <- Value.create()   ThreadCondition cond <- ThreadCondition.new() -  Thread thread1 <- ProcessThread.from(WaitAndUpdate.create(value,cond)).start()-  Thread thread2 <- ProcessThread.from(WaitAndUpdate.create(value,cond)).start()+  Thread thread1 <- ProcessThread.from(WaitAndUpdate.create(value, cond)).start()+  Thread thread2 <- ProcessThread.from(WaitAndUpdate.create(value, cond)).start()    // Wait for both threads to increment Value once, to indicate readiness.   while (true) {@@ -42,15 +42,15 @@   \ thread1.join()   \ thread2.join() -  \ Testing.checkEquals(value.get(),4)+  \ value.get() `Matches:with` CheckValue:equals(4) }  unittest resumeOne {   Value value <- Value.create()   ThreadCondition cond <- ThreadCondition.new() -  Thread thread1 <- ProcessThread.from(WaitAndUpdate.create(value,cond)).start()-  Thread thread2 <- ProcessThread.from(WaitAndUpdate.create(value,cond)).start()+  Thread thread1 <- ProcessThread.from(WaitAndUpdate.create(value, cond)).start()+  Thread thread2 <- ProcessThread.from(WaitAndUpdate.create(value, cond)).start()    \ Realtime.sleepSeconds(0.01) @@ -69,20 +69,20 @@   \ thread1.join()   \ thread2.join() -  \ Testing.checkEquals(value.get(),3)+  \ value.get() `Matches:with` CheckValue:equals(3) }  unittest forceWaitTimeout {   Value value <- Value.create()   ThreadCondition cond <- ThreadCondition.new() -  Thread thread <- ProcessThread.from(WaitAndUpdate.create(value,cond)).start()+  Thread thread <- ProcessThread.from(WaitAndUpdate.create(value, cond)).start()    \ Realtime.sleepSeconds(0.2)   \ cond.resumeOne()   \ thread.join() -  \ Testing.checkEquals(value.get(),1)+  \ value.get() `Matches:with` CheckValue:equals(1) }  unittest waitNoTimeout {@@ -121,14 +121,14 @@ concrete WaitAndUpdate {   refines Routine -  @type create (Value,ConditionWait) -> (WaitAndUpdate)+  @type create (Value, ConditionWait) -> (WaitAndUpdate) }  define WaitAndUpdate {   @value Value value   @value ConditionWait cond -  create (value,cond) {+  create (value, cond) {     return WaitAndUpdate{ value, cond }   } @@ -150,7 +150,7 @@   testcase "wait() crashes if not locked first" {-  crash+  failure   require "waiting for condition" } @@ -160,7 +160,7 @@   testcase "timedWait() crashes if not locked first" {-  crash+  failure   require "waiting for condition" } @@ -170,7 +170,7 @@   testcase "timedWait() crashes with negative wait" {-  crash+  failure   require "-0\.1" } 
lib/thread/test/thread.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021-2022 Kevin P. Barry+Copyright 2021-2023 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.@@ -17,16 +17,16 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "simple Thread test" {-  success+  success TestChecker }  unittest test {   CountLoop counter <- CountLoop.create(10000)-  \ Testing.checkEquals(counter.get(),0)+  \ counter.get() `Matches:with` CheckValue:equals(0)   \ counter.start()-  \ Testing.checkEquals(counter.get(),10000)+  \ counter.get() `Matches:with` CheckValue:equals(10000)   \ counter.start()-  \ Testing.checkEquals(counter.get(),20000)+  \ counter.get() `Matches:with` CheckValue:equals(20000) }  concrete CountLoop {@@ -79,17 +79,17 @@   testcase "ProcessThread mutex integration test" {-  success+  success TestChecker }  unittest test {   Mutex mutex <- SimpleMutex.new()   Value value <- Value.create()-  Thread evenThread <- ProcessThread.from(EvenOrOdd.create(mutex,true, 10,value)).start()-  Thread oddThread  <- ProcessThread.from(EvenOrOdd.create(mutex,false,10,value)).start()+  Thread evenThread <- ProcessThread.from(EvenOrOdd.create(mutex, true, 10, value)).start()+  Thread oddThread  <- ProcessThread.from(EvenOrOdd.create(mutex, false, 10, value)).start()   \ evenThread.join()   \ oddThread.join()-  \ Testing.checkEquals(value.get(),20)+  \ value.get() `Matches:with` CheckValue:equals(20) }  concrete EvenOrOdd {@@ -100,7 +100,7 @@   // - Bool:  Increment only on even if true, or on odd if false.   // - Int:   Number of increment operations.   // - Value: Value to increment.-  @type create (Mutex,Bool,Int,Value) -> (Routine)+  @type create (Mutex, Bool, Int, Value) -> (Routine) }  define EvenOrOdd {@@ -109,7 +109,7 @@   @value Int count   @value Value value -  create (m,e,c,v) {+  create (m, e, c, v) {     return EvenOrOdd{ m, e, c, v }   } @@ -143,7 +143,7 @@   testcase "Argv available in Thread" {-  success+  success TestChecker   args "arg1" } @@ -163,13 +163,13 @@   }    run () {-    \ Testing.checkEquals(Argv.global().readAt(1),"arg1")+    \ Argv.global().readAt(1) `Matches:with` CheckValue:equals("arg1")   } }   testcase "join() crashes if Thread not started yet" {-  crash+  failure   require "thread.*started" } @@ -188,7 +188,7 @@   testcase "join() twice crashes" {-  crash+  failure   require "thread.*started" } @@ -198,7 +198,7 @@   testcase "detach() crashes if Thread not started yet" {-  crash+  failure   require "thread.*started" } @@ -217,7 +217,7 @@   testcase "detach() twice crashes" {-  crash+  failure   require "thread.*started" } @@ -246,7 +246,7 @@   testcase "creation tracing in Thread" {-  crash+  failure   // Thread creation.   require "CrashThread\.new"   // Inherited trace from start call.
lib/util/.zeolite-module view
@@ -10,7 +10,7 @@     expression: \x1000   } ]-private_deps: [+public_deps: [   "lib/testing" ] extra_files: [@@ -43,4 +43,4 @@     categories: [SpinlockMutex]   } ]-mode: incremental {}+mode: incremental { }
lib/util/counters.0rp view
@@ -31,7 +31,7 @@ // Creates an Order<#x> that repeats a single value, for use with traverse. concrete Repeat<#x> {   // Repeat the value the specified number of times.-  @category times<#y>     (#y,Int) -> (optional Order<#y>)+  @category times<#y>     (#y, Int) -> (optional Order<#y>)   // Repeat the value an unlimited number of times.   @category unlimited<#y> (#y)     -> (optional Order<#y>) }@@ -41,17 +41,17 @@   // Get the lower value. (Defaults to the first value.)   @category min<#x>     #x defines LessThan<#x>-  (#x,#x) -> (#x)+  (#x, #x) -> (#x)    // Get the higher value. (Defaults to the second value.)   @category max<#x>     #x defines LessThan<#x>-  (#x,#x) -> (#x)+  (#x, #x) -> (#x)    // Determine the lower and higher values. (Defaults to the same order.)   @category minMax<#x>     #x defines LessThan<#x>-  (#x,#x) -> (#x,#x)+  (#x, #x) -> (#x, #x) }  // Builds a sequence of values.
lib/util/extra.0rp view
@@ -63,6 +63,8 @@    // Get the contained value. Crashes if there is no value.   @value getValue () -> (#x)+  // Get the contained value. Returns empty if there is no value.+  @value tryValue () -> (optional #x)   // Get the error message. Crashes if there is no error.   @value getError () -> (Formatted)   // Convert the error to any other ErrorOr type. Crashes if there is no error.@@ -81,7 +83,7 @@   // Notes:   // - When used in unit tests, arg 0 is "testcase" and the remaining args are   //   set from args in the testcase. (See extra.0rt.)-  @type global () -> ([ReadAt<String>&SubSequence])+  @type global () -> ([ReadAt<String> & SubSequence]) }  // A resource that requires explicit cleanup.
lib/util/helpers.0rp view
@@ -29,7 +29,7 @@   //   Bool lt <- x.defaultOrder() `OrderH:lessThan` y.defaultOrder()   @category lessThan<#x>     #x defines LessThan<#x>-  (optional Order<#x>,optional Order<#x>) -> (Bool)+  (optional Order<#x>, optional Order<#x>) -> (Bool)    // The same as lessThan, but with a custom comparator.   //@@ -39,10 +39,10 @@   //   // Example:   //-  //   Bool lt <- x.defaultOrder() `OrderH:lessThanWith<?,Reversed<Int>>` y.defaultOrder()-  @category lessThanWith<#x,#xx>+  //   Bool lt <- x.defaultOrder() `OrderH:lessThanWith<?, Reversed<Int>>` y.defaultOrder()+  @category lessThanWith<#x, #xx>     #xx defines LessThan<#x>-  (optional Order<#x>,optional Order<#x>) -> (Bool)+  (optional Order<#x>, optional Order<#x>) -> (Bool)    // Extend equals, based on position-wise comparisons.   //@@ -51,7 +51,7 @@   //   Bool eq <- x.defaultOrder() `OrderH:equals` y.defaultOrder()   @category equals<#x>     #x defines Equals<#x>-  (optional Order<#x>,optional Order<#x>) -> (Bool)+  (optional Order<#x>, optional Order<#x>) -> (Bool)    // The same as equals, but with a custom comparator.   //@@ -61,10 +61,10 @@   //   // Example:   //-  //   Bool eq <- x.defaultOrder() `OrderH:equalsWith<?,BySize>` y.defaultOrder()-  @category equalsWith<#x,#xx>+  //   Bool eq <- x.defaultOrder() `OrderH:equalsWith<?, BySize>` y.defaultOrder()+  @category equalsWith<#x, #xx>     #xx defines Equals<#x>-  (optional Order<#x>,optional Order<#x>) -> (Bool)+  (optional Order<#x>, optional Order<#x>) -> (Bool)    // Copies references to all elements to the destination.   //@@ -78,9 +78,9 @@   //   // Returns:   // - #c: The container originally passed.-  @category copyTo<#x,#c>+  @category copyTo<#x, #c>     #c requires Append<#x>-  (optional Order<#x>,#c) -> (#c)+  (optional Order<#x>, #c) -> (#c)    // Duplicates all elements to the destination.   //@@ -94,10 +94,10 @@   //   // Returns:   // - #c: The container originally passed.-  @category duplicateTo<#x,#c>+  @category duplicateTo<#x, #c>     #x requires Duplicate     #c requires Append<#x>-  (optional Order<#x>,#c) -> (#c)+  (optional Order<#x>, #c) -> (#c) }  // Helpers to extend functionality to the ReadAt<#x> built-in.@@ -113,7 +113,7 @@   //   Bool lt <- x `ReadAtH:lessThan` y   @category lessThan<#x>     #x defines LessThan<#x>-  (ReadAt<#x>,ReadAt<#x>) -> (Bool)+  (ReadAt<#x>, ReadAt<#x>) -> (Bool)    // The same as lessThan, but with a custom comparator.   //@@ -123,10 +123,10 @@   //   // Example:   //-  //   Bool lt <- x `ReadAtH:lessThanWith<?,Reversed<Int>>` y-  @category lessThanWith<#x,#xx>+  //   Bool lt <- x `ReadAtH:lessThanWith<?, Reversed<Int>>` y+  @category lessThanWith<#x, #xx>     #xx defines LessThan<#x>-  (ReadAt<#x>,ReadAt<#x>) -> (Bool)+  (ReadAt<#x>, ReadAt<#x>) -> (Bool)    // Extend equals, based on position-wise comparisons.   //@@ -135,7 +135,7 @@   //   Bool eq <- x `ReadAtH:equals` y   @category equals<#x>     #x defines Equals<#x>-  (ReadAt<#x>,ReadAt<#x>) -> (Bool)+  (ReadAt<#x>, ReadAt<#x>) -> (Bool)    // The same as equals, but with a custom comparator.   //@@ -145,10 +145,10 @@   //   // Example:   //-  //   Bool eq <- x `ReadAtH:equalsWith<?,BySize>` y-  @category equalsWith<#x,#xx>+  //   Bool eq <- x `ReadAtH:equalsWith<?, BySize>` y+  @category equalsWith<#x, #xx>     #xx defines Equals<#x>-  (ReadAt<#x>,ReadAt<#x>) -> (Bool)+  (ReadAt<#x>, ReadAt<#x>) -> (Bool)    // Copies references to all elements to the destination.   //@@ -162,9 +162,9 @@   //   // Returns:   // - #c: The container originally passed.-  @category copyTo<#x,#c>+  @category copyTo<#x, #c>     #c requires Append<#x>-  (ReadAt<#x>,#c) -> (#c)+  (ReadAt<#x>, #c) -> (#c)    // Duplicates all elements to the destination.   //@@ -178,10 +178,10 @@   //   // Returns:   // - #c: The container originally passed.-  @category duplicateTo<#x,#c>+  @category duplicateTo<#x, #c>     #x requires Duplicate     #c requires Append<#x>-  (ReadAt<#x>,#c) -> (#c)+  (ReadAt<#x>, #c) -> (#c)    // Iterates over the container from 0 to the end.   @category forwardOrder<#x> (ReadAt<#x>) -> (optional Order<#x>)@@ -190,7 +190,7 @@   @category reverseOrder<#x> (ReadAt<#x>) -> (optional Order<#x>)    // Iterates over the container using the provided index order.-  @category iterateWith<#x> (ReadAt<#x>,optional Order<Int>) -> (optional Order<#x>)+  @category iterateWith<#x> (ReadAt<#x>, optional Order<Int>) -> (optional Order<#x>) }  // Helpers to extend functionality to the Formatted built-in.
lib/util/interfaces.0rp view
@@ -18,5 +18,5 @@  // A @value version of the LessThan @type interface. @value interface LessThan2<#x|> {-  lessThan2 (#x,#x) -> (Bool)+  lessThan2 (#x, #x) -> (Bool) }
lib/util/src/counters.0rx view
@@ -64,7 +64,7 @@       actualStart <- start + increment*(require(actualCount)-1)       actualIncrement <- -increment     }-    return IntCounter.new(actualStart,actualIncrement,actualCount)+    return IntCounter.new(actualStart, actualIncrement, actualCount)   }    start (x) {@@ -96,7 +96,7 @@ }  concrete IntCounter {-  @type new (Int,Int,optional Int) -> (optional Order<Int>)+  @type new (Int, Int, optional Int) -> (optional Order<Int>) }  define IntCounter {@@ -108,11 +108,11 @@   @value Int increment   @value optional Int remaining -  new (start,increment,count) {+  new (start, increment, count) {     if (`present` count && `require` count <= 0) {       return empty     } else {-      return #self{ start, increment, count }+      return delegate -> #self     }   } @@ -141,7 +141,7 @@   @value #x value   @value Order<any> counter -  times (value,max) {+  times (value, max) {     optional Order<any> counter <- Counter.builder().count(max).done()     if (! `present` counter) {       return empty@@ -170,15 +170,15 @@ }  define Ranges {-  min (x,y) {-    return minMax(x,y){0}+  min (x, y) {+    return minMax(x, y){0}   } -  max (x,y) (z) {-    return minMax(x,y){1}+  max (x, y) (z) {+    return minMax(x, y){1}   } -  minMax (x,y) {+  minMax (x, y) {     // NOTE: Using y < x makes the default x, y when they are equal.     if (y `#x.lessThan` x) {       return y, x
lib/util/src/extra.0rx view
@@ -31,11 +31,11 @@     return "Void"   } -  equals (_,_) {+  equals (_, _) {     return true   } -  lessThan (_,_) {+  lessThan (_, _) {     return false   } @@ -67,7 +67,7 @@     fail("container is always empty")   } -  writeAt (_,_) {+  writeAt (_, _) {     fail("container is always empty")   } }@@ -96,13 +96,17 @@     }   } +  tryValue () {+    return maybeValue+  }+   getError () {     return require(maybeError)   }    convertError () {     scoped {-      optional ErrorOr<all> error <- reduce<#self,ErrorOr<all>>(self)+      optional ErrorOr<all> error <- reduce<#self, ErrorOr<all>>(self)     } in if (present(error)) {       return require(error)     } else {
lib/util/src/helpers.0rx view
@@ -17,16 +17,16 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define OrderH {-  lessThan (x,y) {-    return lessThanWith<#x,#x>(x,y)+  lessThan (x, y) {+    return lessThanWith<#x, #x>(x, y)   } -  lessThanWith (x,y) {+  lessThanWith (x, y) {     optional Order<#x> xx <- x     optional Order<#x> yy <- y-    $Hidden[x,y]$+    $Hidden[x, y]$     while (present(xx) && present(yy)) {-      $ReadOnly[xx,yy]$+      $ReadOnly[xx, yy]$       if (require(xx).get() `#xx.lessThan` require(yy).get()) {         return true       } elif (require(yy).get() `#xx.lessThan` require(xx).get()) {@@ -39,16 +39,16 @@     return present(yy)   } -  equals (x,y) {-    return equalsWith<#x,#x>(x,y)+  equals (x, y) {+    return equalsWith<#x, #x>(x, y)   } -  equalsWith (x,y) {+  equalsWith (x, y) {     optional Order<#x> xx <- x     optional Order<#x> yy <- y-    $Hidden[x,y]$+    $Hidden[x, y]$     while (present(xx) && present(yy)) {-      $ReadOnly[xx,yy]$+      $ReadOnly[xx, yy]$       if (!(require(xx).get() `#xx.equals` require(yy).get())) {         return false       }@@ -59,7 +59,7 @@     return !present(xx) && !present(yy)   } -  copyTo (input,output) (original) {+  copyTo (input, output) (original) {     original <- output     $Hidden[original]$     traverse (input -> #x value) {@@ -67,7 +67,7 @@     }   } -  duplicateTo (input,output) (original) {+  duplicateTo (input, output) (original) {     original <- output     $Hidden[original]$     traverse (input -> #x value) {@@ -77,11 +77,11 @@ }  define ReadAtH {-  lessThan (x,y) {-    return lessThanWith<#x,#x>(x,y)+  lessThan (x, y) {+    return lessThanWith<#x, #x>(x, y)   } -  lessThanWith (x,y) {+  lessThanWith (x, y) {     traverse (`Counter.zeroIndexed` (x.size() `Ranges:min` y.size()) -> Int i) {       $ReadOnly[i]$       if (x.readAt(i) `#xx.lessThan` y.readAt(i)) {@@ -93,11 +93,11 @@     return x.size() < y.size()   } -  equals (x,y) {-    return equalsWith<#x,#x>(x,y)+  equals (x, y) {+    return equalsWith<#x, #x>(x, y)   } -  equalsWith (x,y) {+  equalsWith (x, y) {     if (x.size() != y.size()) {       return false     }@@ -110,7 +110,7 @@     return true   } -  copyTo (input,output) (original) {+  copyTo (input, output) (original) {     original <- output     $Hidden[original]$     traverse (`Counter.zeroIndexed` input.size() -> Int i) {@@ -118,7 +118,7 @@     }   } -  duplicateTo (input,output) (original) {+  duplicateTo (input, output) (original) {     original <- output     $Hidden[original]$     traverse (`Counter.zeroIndexed` input.size() -> Int i) {@@ -134,7 +134,7 @@     return input `iterateWith` `Counter.revZeroIndexed` input.size()   } -  iterateWith (input,order) {+  iterateWith (input, order) {     return input `IndexOrder:iterateWith` order   } }@@ -143,7 +143,7 @@   try (x) {     if (present(x)) {       scoped {-        optional Formatted formatted <- reduce<#x,Formatted>(x)+        optional Formatted formatted <- reduce<#x, Formatted>(x)       } in if (present(formatted)) {         return require(formatted)       } else {@@ -164,7 +164,7 @@ concrete IndexOrder<#x> {   refines Order<#x> -  @category iterateWith<#x> (ReadAt<#x>,optional Order<Int>) -> (optional Order<#x>)+  @category iterateWith<#x> (ReadAt<#x>, optional Order<Int>) -> (optional Order<#x>) }  define IndexOrder {@@ -173,7 +173,7 @@   @value ReadAt<#x> container   @value Order<Int> index -  iterateWith (container,index) {+  iterateWith (container, index) {     if (`present` index) {       return IndexOrder<#x>{ container, `require` index }     } else {@@ -198,27 +198,27 @@ }  define Reversed {-  lessThan (x,y) {+  lessThan (x, y) {     return y `#x.lessThan` x   } }  define BySize {-  equals (x,y) {+  equals (x, y) {     return x.size() == y.size()   } -  lessThan (x,y) {+  lessThan (x, y) {     return x.size() < y.size()   } }  define AlwaysEqual {-  equals (_,_) {+  equals (_, _) {     return true   } -  lessThan (_,_) {+  lessThan (_, _) {     return false   } }@@ -227,10 +227,10 @@   refines LessThan2<#x>    new () {-    return #self{ }+    return delegate -> #self   } -  lessThan2 (x,y) {+  lessThan2 (x, y) {     return x `#xx.lessThan` y   } }
lib/util/src/input.0rx view
@@ -25,7 +25,7 @@   }    readAll (reader) {-    [Append<Formatted>&Build<String>] builder <- String.builder()+    [Append<Formatted> & Build<String>] builder <- String.builder()     while (!reader.pastEnd()) {       \ builder.append(reader.readBlock($ExprLookup[BLOCK_READ_SIZE]$))     }@@ -69,8 +69,8 @@    @value takeLine (Int) -> (String)   takeLine (position) {-    String data <- buffer.subSequence(0,position)-    buffer <- buffer.subSequence(position+1,buffer.size()-position-1)+    String data <- buffer.subSequence(0, position)+    buffer <- buffer.subSequence(position+1, buffer.size()-position-1)     return data   } }
lib/util/src/parse.0rx view
@@ -95,7 +95,7 @@     }      total <- sign*total-    $Hidden[sign,hasDigit]$+    $Hidden[sign, hasDigit]$      Int expSign <- 0     Int exp <- 0@@ -107,7 +107,7 @@         Char c <- require(curr).get()         curr <- require(curr).next()         $ReadOnly[c]$-        $Hidden[curr,total]$+        $Hidden[curr, total]$         if (expSign == 0) {           if (c == '-') {             expSign <- -1
lib/util/src/testing.0rx view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2023 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.@@ -16,43 +16,74 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -$TestsOnly$+define CheckErrorOr {+  $ReadOnlyExcept[]$ -define UtilTesting {-  checkError (x) {-    if (!x.isError()) {-      fail(String.builder()-          .append("expected an error but got value ")-          .append(x.getValue())-          .build())-    }+  refines ValueMatcher<ErrorOr<#x>>++  @value optional ValueMatcher<#x> valueMatcher+  @value optional ValueMatcher<String> errorMatcher++  value (valueMatcher) {+    return CheckErrorOr<#x>{ valueMatcher, empty }   } -  checkSuccess (x,y) {-    if (x.isError()) {-      fail(String.builder()-          .append("expected ")-          .append(y)-          .append(" but got error ")-          .append(x.getError())-          .build())-    } else {-      \ Testing.checkEquals(x.getValue(),y)+  error (errorMatcher) {+    return CheckErrorOr<any>{ empty, errorMatcher }+  }++  check (actual, report) {+    optional #x value <- empty+    if (`present` actual && !require(actual).isError()) {+      value <- require(actual).getValue()     }+    optional String error <- empty+    if (`present` actual && require(actual).isError()) {+      error <- require(actual).getError().formatted()+    }+    MultiChecker checker <- MultiChecker.new(report)+    if (`present` valueMatcher) {+      \ checker.tryCheck(title: "value", value, require(valueMatcher))+    } elif (`present` value) {+      optional Formatted formattedValue <- reduce<#y, ErrorOr<Formatted>>(actual)&.getValue()+      if (`present` formattedValue) {+      \ report.newSection(title: "value")+          .addError(message: String.builder()+              .append("expected empty but got \"")+              .append(`require` formattedValue)+              .append("\"")+              .build())+      } else {+      \ report.newSection(title: "value")+          .addError(message: String.builder()+              .append("expected empty but got ")+              .append(typename<#y>())+              .build())+      }+    }+    if (`present` errorMatcher) {+      \ checker.tryCheck(title: "error", error, require(errorMatcher))+    } elif (`present` error) {+      \ report.newSection(title: "error")+          .addError(message: String.builder()+              .append("expected empty but got \"")+              .append(require(error).formatted())+              .append("\"")+              .build())+    }   } -  checkSuccessBetween (x,l,h) {-    if (x.isError()) {-      fail(String.builder()-          .append("expected value between ")-          .append(l)-          .append(" and ")-          .append(h)-          .append(" but got error ")-          .append(x.getError())-          .build())+  summary () {+    if (present(valueMatcher)) {+      return String.builder()+          .append(typename<ErrorOr<#x>>())+          .append(" has matching value")+          .build()     } else {-      \ Testing.checkBetween(x.getValue(),l,h)+      return String.builder()+          .append(typename<ErrorOr<#x>>())+          .append(" has error")+          .build()     }   } }
lib/util/test/counters.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021-2022 Kevin P. Barry+Copyright 2021-2023 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.@@ -17,18 +17,18 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "counter tests" {-  success+  success TestChecker }  unittest zeroIndexed {   Int index <- 0    traverse (Counter.zeroIndexed(10) -> Int i) {-    \ Testing.checkEquals(i,index)+    \ i `Matches:with` CheckValue:equals(index)     index <- index+1   } -  \ Testing.checkEquals(index,10)+  \ index `Matches:with` CheckValue:equals(10) }  unittest zeroIndexedEmpty {@@ -41,11 +41,11 @@   Int index <- 9    traverse (Counter.revZeroIndexed(10) -> Int i) {-    \ Testing.checkEquals(i,index)+    \ i `Matches:with` CheckValue:equals(index)     index <- index-1   } -  \ Testing.checkEquals(index,-1)+  \ index `Matches:with` CheckValue:equals(-1) }  unittest revZeroIndexedEmpty {@@ -58,13 +58,13 @@   Int index <- 0    traverse (Counter.unlimited() -> Int i) {-    \ Testing.checkEquals(i,index)+    \ i `Matches:with` CheckValue:equals(index)     if ((index <- index+1) >= 10) {       break     }   } -  \ Testing.checkEquals(index,10)+  \ index `Matches:with` CheckValue:equals(10) }  unittest builderReversePositive {@@ -77,11 +77,11 @@                 .limit(17)                 .reverse()                 .done() -> Int i) {-    \ Testing.checkEquals(i,index)+    \ i `Matches:with` CheckValue:equals(index)     index <- index-5   } -  \ Testing.checkEquals(index,-2)+  \ index `Matches:with` CheckValue:equals(-2) }  unittest builderReverseNegative {@@ -94,22 +94,22 @@                 .limit(3)                 .reverse()                 .done() -> Int i) {-    \ Testing.checkEquals(i,index)+    \ i `Matches:with` CheckValue:equals(index)     index <- index+5   } -  \ Testing.checkEquals(index,22)+  \ index `Matches:with` CheckValue:equals(22) }  unittest times {   Int index <- 0    traverse ("message" `Repeat:times` 10 -> String m) {-    \ Testing.checkEquals(m,"message")+    \ m `Matches:with` CheckValue:equals("message")     index <- index+1   } -  \ Testing.checkEquals(index,10)+  \ index `Matches:with` CheckValue:equals(10) }  unittest timesEmpty {@@ -122,47 +122,47 @@   Int index <- 0    traverse (Repeat:unlimited("message") -> String m) {-    \ Testing.checkEquals(m,"message")+    \ m `Matches:with` CheckValue:equals("message")     if ((index <- index+1) >= 10) {       break     }   } -  \ Testing.checkEquals(index,10)+  \ index `Matches:with` CheckValue:equals(10) }  unittest minMax {   scoped {-    Int x, Int y <- Ranges:minMax(10,3)+    Int x, Int y <- Ranges:minMax(10, 3)   } in {-    \ Testing.checkEquals(x,3)-    \ Testing.checkEquals(y,10)+    \ x `Matches:with` CheckValue:equals(3)+    \ y `Matches:with` CheckValue:equals(10)   }    scoped {-    Int x, Int y <- Ranges:minMax(3,10)+    Int x, Int y <- Ranges:minMax(3, 10)   } in {-    \ Testing.checkEquals(x,3)-    \ Testing.checkEquals(y,10)+    \ x `Matches:with` CheckValue:equals(3)+    \ y `Matches:with` CheckValue:equals(10)   } }  unittest min {   scoped {-    Int x <- Ranges:min(10,3)-  } in \ Testing.checkEquals(x,3)+    Int x <- Ranges:min(10, 3)+  } in \ x `Matches:with` CheckValue:equals(3)    scoped {-    Int x <- Ranges:min(3,10)-  } in \ Testing.checkEquals(x,3)+    Int x <- Ranges:min(3, 10)+  } in \ x `Matches:with` CheckValue:equals(3) }  unittest max {   scoped {-    Int x <- Ranges:max(10,3)-  } in \ Testing.checkEquals(x,10)+    Int x <- Ranges:max(10, 3)+  } in \ x `Matches:with` CheckValue:equals(10)    scoped {-    Int x <- Ranges:max(3,10)-  } in \ Testing.checkEquals(x,10)+    Int x <- Ranges:max(3, 10)+  } in \ x `Matches:with` CheckValue:equals(10) }
lib/util/test/extra.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -17,31 +17,31 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "Argv checks" {-  success+  success TestChecker   args "arg1" "arg2" "arg3" "arg4" }  unittest global {   Int count <- Argv.global().size()-  \ Testing.checkEquals(count,5)-  \ Testing.checkEquals(Argv.global().readAt(0),"testcase")-  \ Testing.checkEquals(Argv.global().readAt(1),"arg1")-  \ Testing.checkEquals(Argv.global().readAt(2),"arg2")-  \ Testing.checkEquals(Argv.global().readAt(3),"arg3")-  \ Testing.checkEquals(Argv.global().readAt(4),"arg4")+  \ count `Matches:with` CheckValue:equals(5)+  \ Argv.global().readAt(0) `Matches:with` CheckValue:equals("testcase")+  \ Argv.global().readAt(1) `Matches:with` CheckValue:equals("arg1")+  \ Argv.global().readAt(2) `Matches:with` CheckValue:equals("arg2")+  \ Argv.global().readAt(3) `Matches:with` CheckValue:equals("arg3")+  \ Argv.global().readAt(4) `Matches:with` CheckValue:equals("arg4") }  unittest subSequence {-  ReadAt<String> argv <- Argv.global().subSequence(2,2)+  ReadAt<String> argv <- Argv.global().subSequence(2, 2)   Int count <- argv.size()-  \ Testing.checkEquals(count,2)-  \ Testing.checkEquals(argv.readAt(0),"arg2")-  \ Testing.checkEquals(argv.readAt(1),"arg3")+  \ count `Matches:with` CheckValue:equals(2)+  \ argv.readAt(0) `Matches:with` CheckValue:equals("arg2")+  \ argv.readAt(1) `Matches:with` CheckValue:equals("arg3") }   testcase "Argv readAt out of bounds" {-  crash+  failure   require "index 5" } @@ -51,41 +51,43 @@   testcase "Argv subSequence out of bounds" {-  crash+  failure   require "index 5" }  unittest test {-  \ Argv.global().subSequence(5,1)+  \ Argv.global().subSequence(5, 1) }   testcase "ErrorOr checks" {-  success+  success TestChecker }  unittest withValue {   ErrorOr<Int> value <- ErrorOr:value<Int>(10)-  \ Testing.checkFalse(value.isError())-  \ Testing.checkEquals(value.getValue(),10)+  \ value.isError() `Matches:with` CheckValue:equals(false)+  \ value.getValue() `Matches:with` CheckValue:equals(10)+  \ value.tryValue() `Matches:with` CheckValue:equals(10) }  unittest withError {   ErrorOr<String> value <- ErrorOr:error("error message")-  \ Testing.checkTrue(value.isError())-  \ Testing.checkEquals(value.getError().formatted(),"error message")+  \ value.isError() `Matches:with` CheckValue:equals(true)+  \ value.tryValue() `Matches:with` CheckValue:equals(empty?String)+  \ value.getError().formatted() `Matches:with` CheckValue:equals("error message") }  unittest convertError {   scoped {     ErrorOr<String> error <- ErrorOr:error("error message")   } in ErrorOr<Int> value <- error.convertError()-  \ Testing.checkEquals(value.getError().formatted(),"error message")+  \ value.getError().formatted() `Matches:with` CheckValue:equals("error message") }   testcase "ErrorOr getError() crashes with value" {-  crash+  failure   require "empty" } @@ -96,7 +98,7 @@   testcase "ErrorOr getValue() crashes with error" {-  crash+  failure   require "error message" } @@ -107,7 +109,7 @@   testcase "ErrorOr convertError() crashes with no error" {-  crash+  failure   require "no error" } @@ -118,28 +120,28 @@   testcase "Void tests" {-  success+  success TestChecker }  unittest formatted {-  \ Testing.checkEquals(Void.default().formatted(),"Void")+  \ Void.default().formatted() `Matches:with` CheckValue:equals("Void") }  unittest lessThan {-  \ Testing.checkFalse(Void.default() `Void.lessThan` Void.default())+  \ Void.default() `Void.lessThan` Void.default() `Matches:with` CheckValue:equals(false) }  unittest equals {-  \ Testing.checkTrue(Void.default() `Void.equals` Void.default())+  \ Void.default() `Void.equals` Void.default() `Matches:with` CheckValue:equals(true) }  unittest hashed {-  \ Testing.checkEquals(Void.default().duplicate().hashed(),Void.default().hashed())+  \ Void.default().duplicate().hashed() `Matches:with` CheckValue:equals(Void.default().hashed()) }   testcase "AlwaysEmpty tests" {-  success+  success TestChecker }  unittest conversions {@@ -148,11 +150,11 @@ }  unittest size {-  \ Testing.checkEquals(AlwaysEmpty.default().size(),0)+  \ AlwaysEmpty.default().size() `Matches:with` CheckValue:equals(0) }  unittest duplicate {-  \ Testing.checkEquals(AlwaysEmpty.default().duplicate().size(),0)+  \ AlwaysEmpty.default().duplicate().size() `Matches:with` CheckValue:equals(0) }  unittest defaultOrder {@@ -163,7 +165,7 @@   testcase "AlwaysEmpty.readAt fails" {-  crash+  failure   require "empty" } @@ -173,10 +175,10 @@   testcase "AlwaysEmpty.writeAt fails" {-  crash+  failure   require "empty" }  unittest readAt {-  \ AlwaysEmpty.default().writeAt(0,123)+  \ AlwaysEmpty.default().writeAt(0, 123) }
lib/util/test/helpers.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,73 +17,73 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "comparator helper tests" {-  success+  success TestChecker }  unittest orderHLessThan {-  \ Testing.checkFalse("".defaultOrder()    `OrderH:lessThan` "".defaultOrder())-  \ Testing.checkTrue("a".defaultOrder()    `OrderH:lessThan` "abc".defaultOrder())-  \ Testing.checkFalse("b".defaultOrder()   `OrderH:lessThan` "abc".defaultOrder())-  \ Testing.checkFalse("abc".defaultOrder() `OrderH:lessThan` "abc".defaultOrder())-  \ Testing.checkFalse("abc".defaultOrder() `OrderH:lessThan` "a".defaultOrder())-  \ Testing.checkTrue("abc".defaultOrder()  `OrderH:lessThan` "b".defaultOrder())+  \ "".defaultOrder()    `OrderH:lessThan` "".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "a".defaultOrder()    `OrderH:lessThan` "abc".defaultOrder() `Matches:with` CheckValue:equals(true)+  \ "b".defaultOrder()   `OrderH:lessThan` "abc".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "abc".defaultOrder() `OrderH:lessThan` "abc".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "abc".defaultOrder() `OrderH:lessThan` "a".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "abc".defaultOrder()  `OrderH:lessThan` "b".defaultOrder() `Matches:with` CheckValue:equals(true) }  unittest orderHLessThanWith {-  \ Testing.checkFalse("".defaultOrder()    `OrderH:lessThanWith<?,Reversed<Char>>` "".defaultOrder())-  \ Testing.checkTrue("a".defaultOrder()    `OrderH:lessThanWith<?,Reversed<Char>>` "abc".defaultOrder())-  \ Testing.checkTrue("b".defaultOrder()    `OrderH:lessThanWith<?,Reversed<Char>>` "abc".defaultOrder())-  \ Testing.checkFalse("abc".defaultOrder() `OrderH:lessThanWith<?,Reversed<Char>>` "abc".defaultOrder())-  \ Testing.checkFalse("abc".defaultOrder() `OrderH:lessThanWith<?,Reversed<Char>>` "a".defaultOrder())-  \ Testing.checkFalse("abc".defaultOrder() `OrderH:lessThanWith<?,Reversed<Char>>` "b".defaultOrder())+  \ "".defaultOrder()    `OrderH:lessThanWith<?, Reversed<Char>>` "".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "a".defaultOrder()    `OrderH:lessThanWith<?, Reversed<Char>>` "abc".defaultOrder() `Matches:with` CheckValue:equals(true)+  \ "b".defaultOrder()    `OrderH:lessThanWith<?, Reversed<Char>>` "abc".defaultOrder() `Matches:with` CheckValue:equals(true)+  \ "abc".defaultOrder() `OrderH:lessThanWith<?, Reversed<Char>>` "abc".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "abc".defaultOrder() `OrderH:lessThanWith<?, Reversed<Char>>` "a".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "abc".defaultOrder() `OrderH:lessThanWith<?, Reversed<Char>>` "b".defaultOrder() `Matches:with` CheckValue:equals(false) }  unittest orderHEquals {-  \ Testing.checkTrue("".defaultOrder()     `OrderH:equals` "".defaultOrder())-  \ Testing.checkFalse("a".defaultOrder()   `OrderH:equals` "abc".defaultOrder())-  \ Testing.checkTrue("abc".defaultOrder()  `OrderH:equals` "abc".defaultOrder())-  \ Testing.checkFalse("abc".defaultOrder() `OrderH:equals` "a".defaultOrder())+  \ "".defaultOrder()     `OrderH:equals` "".defaultOrder() `Matches:with` CheckValue:equals(true)+  \ "a".defaultOrder()   `OrderH:equals` "abc".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "abc".defaultOrder()  `OrderH:equals` "abc".defaultOrder() `Matches:with` CheckValue:equals(true)+  \ "abc".defaultOrder() `OrderH:equals` "a".defaultOrder() `Matches:with` CheckValue:equals(false) }  unittest orderHEqualsWith {-  \ Testing.checkTrue("".defaultOrder()     `OrderH:equalsWith<?,IgnoreCase>` "".defaultOrder())-  \ Testing.checkFalse("a".defaultOrder()   `OrderH:equalsWith<?,IgnoreCase>` "ABC".defaultOrder())-  \ Testing.checkTrue("abc".defaultOrder()  `OrderH:equalsWith<?,IgnoreCase>` "ABC".defaultOrder())-  \ Testing.checkFalse("abc".defaultOrder() `OrderH:equalsWith<?,IgnoreCase>` "DEF".defaultOrder())-  \ Testing.checkFalse("abc".defaultOrder() `OrderH:equalsWith<?,IgnoreCase>` "A".defaultOrder())+  \ "".defaultOrder()     `OrderH:equalsWith<?, IgnoreCase>` "".defaultOrder() `Matches:with` CheckValue:equals(true)+  \ "a".defaultOrder()   `OrderH:equalsWith<?, IgnoreCase>` "ABC".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "abc".defaultOrder()  `OrderH:equalsWith<?, IgnoreCase>` "ABC".defaultOrder() `Matches:with` CheckValue:equals(true)+  \ "abc".defaultOrder() `OrderH:equalsWith<?, IgnoreCase>` "DEF".defaultOrder() `Matches:with` CheckValue:equals(false)+  \ "abc".defaultOrder() `OrderH:equalsWith<?, IgnoreCase>` "A".defaultOrder() `Matches:with` CheckValue:equals(false) }  unittest readAtHLessThan {-  \ Testing.checkFalse(""    `ReadAtH:lessThan` "")-  \ Testing.checkTrue("a"    `ReadAtH:lessThan` "abc")-  \ Testing.checkFalse("b"   `ReadAtH:lessThan` "abc")-  \ Testing.checkFalse("abc" `ReadAtH:lessThan` "abc")-  \ Testing.checkFalse("abc" `ReadAtH:lessThan` "a")-  \ Testing.checkTrue("abc"  `ReadAtH:lessThan` "b")+  \ ""    `ReadAtH:lessThan` "" `Matches:with` CheckValue:equals(false)+  \ "a"    `ReadAtH:lessThan` "abc" `Matches:with` CheckValue:equals(true)+  \ "b"   `ReadAtH:lessThan` "abc" `Matches:with` CheckValue:equals(false)+  \ "abc" `ReadAtH:lessThan` "abc" `Matches:with` CheckValue:equals(false)+  \ "abc" `ReadAtH:lessThan` "a" `Matches:with` CheckValue:equals(false)+  \ "abc"  `ReadAtH:lessThan` "b" `Matches:with` CheckValue:equals(true) }  unittest readAtHLessThanWith {-  \ Testing.checkFalse(""    `ReadAtH:lessThanWith<?,Reversed<Char>>` "")-  \ Testing.checkTrue("a"    `ReadAtH:lessThanWith<?,Reversed<Char>>` "abc")-  \ Testing.checkTrue("b"    `ReadAtH:lessThanWith<?,Reversed<Char>>` "abc")-  \ Testing.checkFalse("abc" `ReadAtH:lessThanWith<?,Reversed<Char>>` "abc")-  \ Testing.checkFalse("abc" `ReadAtH:lessThanWith<?,Reversed<Char>>` "a")-  \ Testing.checkFalse("abc" `ReadAtH:lessThanWith<?,Reversed<Char>>` "b")+  \ ""    `ReadAtH:lessThanWith<?, Reversed<Char>>` "" `Matches:with` CheckValue:equals(false)+  \ "a"    `ReadAtH:lessThanWith<?, Reversed<Char>>` "abc" `Matches:with` CheckValue:equals(true)+  \ "b"    `ReadAtH:lessThanWith<?, Reversed<Char>>` "abc" `Matches:with` CheckValue:equals(true)+  \ "abc" `ReadAtH:lessThanWith<?, Reversed<Char>>` "abc" `Matches:with` CheckValue:equals(false)+  \ "abc" `ReadAtH:lessThanWith<?, Reversed<Char>>` "a" `Matches:with` CheckValue:equals(false)+  \ "abc" `ReadAtH:lessThanWith<?, Reversed<Char>>` "b" `Matches:with` CheckValue:equals(false) }  unittest readAtHEquals {-  \ Testing.checkTrue(""     `ReadAtH:equals` "")-  \ Testing.checkFalse("a"   `ReadAtH:equals` "abc")-  \ Testing.checkTrue("abc"  `ReadAtH:equals` "abc")-  \ Testing.checkFalse("abc" `ReadAtH:equals` "a")+  \ ""     `ReadAtH:equals` "" `Matches:with` CheckValue:equals(true)+  \ "a"   `ReadAtH:equals` "abc" `Matches:with` CheckValue:equals(false)+  \ "abc"  `ReadAtH:equals` "abc" `Matches:with` CheckValue:equals(true)+  \ "abc" `ReadAtH:equals` "a" `Matches:with` CheckValue:equals(false) }  unittest readAtHEqualsWith {-  \ Testing.checkTrue(""     `ReadAtH:equalsWith<?,IgnoreCase>` "")-  \ Testing.checkFalse("a"   `ReadAtH:equalsWith<?,IgnoreCase>` "ABC")-  \ Testing.checkTrue("abc"  `ReadAtH:equalsWith<?,IgnoreCase>` "ABC")-  \ Testing.checkFalse("abc" `ReadAtH:equalsWith<?,IgnoreCase>` "DEF")-  \ Testing.checkFalse("abc" `ReadAtH:equalsWith<?,IgnoreCase>` "a")+  \ ""     `ReadAtH:equalsWith<?, IgnoreCase>` "" `Matches:with` CheckValue:equals(true)+  \ "a"   `ReadAtH:equalsWith<?, IgnoreCase>` "ABC" `Matches:with` CheckValue:equals(false)+  \ "abc"  `ReadAtH:equalsWith<?, IgnoreCase>` "ABC" `Matches:with` CheckValue:equals(true)+  \ "abc" `ReadAtH:equalsWith<?, IgnoreCase>` "DEF" `Matches:with` CheckValue:equals(false)+  \ "abc" `ReadAtH:equalsWith<?, IgnoreCase>` "a" `Matches:with` CheckValue:equals(false) }  concrete IgnoreCase {@@ -91,7 +91,7 @@ }  define IgnoreCase {-  equals (x,y) {+  equals (x, y) {     return toLower(x) == toLower(y)   } @@ -106,118 +106,118 @@ }  unittest reversed {-  \ Testing.checkFalse(0 `Reversed<Int>.lessThan` 0)-  \ Testing.checkFalse(0 `Reversed<Int>.lessThan` 1)-  \ Testing.checkTrue(1  `Reversed<Int>.lessThan` 0)+  \ 0 `Reversed<Int>.lessThan` 0 `Matches:with` CheckValue:equals(false)+  \ 0 `Reversed<Int>.lessThan` 1 `Matches:with` CheckValue:equals(false)+  \ 1  `Reversed<Int>.lessThan` 0 `Matches:with` CheckValue:equals(true) }  unittest bySizeLessThan {-  \ Testing.checkFalse(""   `BySize.lessThan` "")-  \ Testing.checkTrue("b"   `BySize.lessThan` "ac")-  \ Testing.checkFalse("ac" `BySize.lessThan` "b")-  \ Testing.checkFalse("a"  `BySize.lessThan` "b")+  \ ""   `BySize.lessThan` "" `Matches:with` CheckValue:equals(false)+  \ "b"   `BySize.lessThan` "ac" `Matches:with` CheckValue:equals(true)+  \ "ac" `BySize.lessThan` "b" `Matches:with` CheckValue:equals(false)+  \ "a"  `BySize.lessThan` "b" `Matches:with` CheckValue:equals(false) }  unittest bySizeEquals {-  \ Testing.checkTrue(""    `BySize.equals` "")-  \ Testing.checkFalse("b"  `BySize.equals` "ac")-  \ Testing.checkFalse("ac" `BySize.equals` "b")-  \ Testing.checkTrue("a"   `BySize.equals` "b")+  \ ""    `BySize.equals` "" `Matches:with` CheckValue:equals(true)+  \ "b"  `BySize.equals` "ac" `Matches:with` CheckValue:equals(false)+  \ "ac" `BySize.equals` "b" `Matches:with` CheckValue:equals(false)+  \ "a"   `BySize.equals` "b" `Matches:with` CheckValue:equals(true) }  unittest alwaysEqualLessThan {-  \ Testing.checkFalse(""   `AlwaysEqual.lessThan` "")-  \ Testing.checkFalse("b"  `AlwaysEqual.lessThan` "ac")-  \ Testing.checkFalse("ac" `AlwaysEqual.lessThan` "b")+  \ ""   `AlwaysEqual.lessThan` "" `Matches:with` CheckValue:equals(false)+  \ "b"  `AlwaysEqual.lessThan` "ac" `Matches:with` CheckValue:equals(false)+  \ "ac" `AlwaysEqual.lessThan` "b" `Matches:with` CheckValue:equals(false) }  unittest alwaysEqualEquals {-  \ Testing.checkTrue(""   `AlwaysEqual.equals` "")-  \ Testing.checkTrue("b"  `AlwaysEqual.equals` "ac")-  \ Testing.checkTrue("ac" `AlwaysEqual.equals` "b")-  \ Testing.checkTrue("a"  `AlwaysEqual.equals` "b")+  \ ""   `AlwaysEqual.equals` "" `Matches:with` CheckValue:equals(true)+  \ "b"  `AlwaysEqual.equals` "ac" `Matches:with` CheckValue:equals(true)+  \ "ac" `AlwaysEqual.equals` "b" `Matches:with` CheckValue:equals(true)+  \ "a"  `AlwaysEqual.equals` "b" `Matches:with` CheckValue:equals(true) }   testcase "iteration tests" {-  success+  success TestChecker }  unittest orderHCopyTo {   ValueCheck output <- ValueCheck.new(10)-  \ ValueOrder.wrap(false,Counter.zeroIndexed(10)) `OrderH:copyTo` output+  \ ValueOrder.wrap(false, Counter.zeroIndexed(10)) `OrderH:copyTo` output   \ output.checkEnd() }  unittest orderHDuplicateTo {   ValueCheck output <- ValueCheck.new(10)-  \ ValueOrder.wrap(true,Counter.zeroIndexed(10)) `OrderH:duplicateTo` output+  \ ValueOrder.wrap(true, Counter.zeroIndexed(10)) `OrderH:duplicateTo` output   \ output.checkEnd() }  unittest readAtHCopyTo {   ValueCheck output <- ValueCheck.new(10)-  \ ValueSource.new(false,10) `ReadAtH:copyTo` output+  \ ValueSource.new(false, 10) `ReadAtH:copyTo` output   \ output.checkEnd() }  unittest readAtHDuplicateTo {   ValueCheck output <- ValueCheck.new(10)-  \ ValueSource.new(true,10) `ReadAtH:duplicateTo` output+  \ ValueSource.new(true, 10) `ReadAtH:duplicateTo` output   \ output.checkEnd() }  unittest readAtHForwardOrder {-  ValueSource source <- ValueSource.new(false,10)+  ValueSource source <- ValueSource.new(false, 10)   Int expected <- 0   traverse (`ReadAtH:forwardOrder` source -> Value actual) {-    \ Testing.checkEquals(actual.get(),expected)+    \ actual.get() `Matches:with` CheckValue:equals(expected)   } update {     expected <- expected+1   }-  \ Testing.checkEquals(expected,10)+  \ expected `Matches:with` CheckValue:equals(10) }  unittest readAtHForwardOrderEmpty {-  ValueSource source <- ValueSource.new(false,0)+  ValueSource source <- ValueSource.new(false, 0)   traverse (`ReadAtH:forwardOrder` source -> _) {     fail("not empty")   } }  unittest readAtHReverseOrder {-  ValueSource source <- ValueSource.new(false,10)+  ValueSource source <- ValueSource.new(false, 10)   Int expected <- 9   traverse (`ReadAtH:reverseOrder` source -> Value actual) {-    \ Testing.checkEquals(actual.get(),expected)+    \ actual.get() `Matches:with` CheckValue:equals(expected)   } update {     expected <- expected-1   }-  \ Testing.checkEquals(expected,-1)+  \ expected `Matches:with` CheckValue:equals(-1) }  unittest readAtHReverseOrderEmpty {-  ValueSource source <- ValueSource.new(false,0)+  ValueSource source <- ValueSource.new(false, 0)   traverse (`ReadAtH:reverseOrder` source -> _) {     fail("not empty")   } }  unittest readAtHIterateWith {-  ValueSource source <- ValueSource.new(false,10)+  ValueSource source <- ValueSource.new(false, 10)   Int expected <- 0   traverse (source `ReadAtH:iterateWith` `Counter.zeroIndexed` 5 -> Value actual) {-    \ Testing.checkEquals(actual.get(),expected)+    \ actual.get() `Matches:with` CheckValue:equals(expected)   } update {     expected <- expected+1   }-  \ Testing.checkEquals(expected,5)+  \ expected `Matches:with` CheckValue:equals(5) }  concrete ValueOrder {   refines Order<Value> -  @type wrap (Bool,optional Order<Int>) -> (optional Order<Value>)+  @type wrap (Bool, optional Order<Int>) -> (optional Order<Value>) }  define ValueOrder {@@ -226,7 +226,7 @@   @value Bool original   @value Order<Int> order -  wrap (original,order) {+  wrap (original, order) {     if (!present(order)) {       return empty     } else {@@ -245,12 +245,12 @@   }    get () {-    return Value.new(original,order.get())+    return Value.new(original, order.get())   } }  concrete ValueCheck {-  // Must append the next value in the sequence [0,size).+  // Must append the next value in the sequence [0, size).   refines Append<Value>    @type new (Int) -> (ValueCheck)@@ -268,11 +268,11 @@   }    checkEnd () {-    \ Testing.checkEquals(current,target)+    \ current `Matches:with` CheckValue:equals(target)   }    append (x) {-    \ Testing.checkEquals(x.get(),current)+    \ x.get() `Matches:with` CheckValue:equals(current)     current <- current+1     return self   }@@ -285,19 +285,19 @@   // Args:   // - Bool: Whether or not the value is "original".   // - Int: Value to return from get().-  @type new (Bool,Int) -> (Value)+  @type new (Bool, Int) -> (Value)    // Crashes if "original" is true.   @value get () -> (Int) }  define Value {-  $ReadOnly[original,value]$+  $ReadOnly[original, value]$    @value Bool original   @value Int value -  new (original,value) {+  new (original, value) {     return Value{ original, value }   } @@ -317,22 +317,22 @@ }  concrete ValueSource {-  // readAt(i) returns Value.new(original,i).+  // readAt(i) returns Value.new(original, i).   refines ReadAt<Value>    // Args:   // - Bool: Whether or not to mark new values as "original".   // - Int: Total size.-  @type new (Bool,Int) -> (ValueSource)+  @type new (Bool, Int) -> (ValueSource) }  define ValueSource {-  $ReadOnly[original,size]$+  $ReadOnly[original, size]$    @value Bool original   @value Int size -  new (original,size) {+  new (original, size) {     return ValueSource{ original, size }   } @@ -341,25 +341,25 @@   }    readAt (i) {-    \ Testing.checkBetween(i,0,size-1)-    return Value.new(original,i)+    \ i `Matches:with` CheckValue:betweenEquals(0, size-1)+    return Value.new(original, i)   } }   testcase "formatting tests" {-  success+  success TestChecker }  unittest emptyValue {-  \ Testing.checkEquals(FormattedH:try<Char>(empty).formatted(),"Char{empty}")-  \ Testing.checkEquals(FormattedH:try(empty).formatted(),"all{empty}")+  \ FormattedH:try<Char>(empty).formatted() `Matches:with` CheckValue:equals("Char{empty}")+  \ FormattedH:try(empty).formatted() `Matches:with` CheckValue:equals("all{empty}") }  unittest formattedValue {-  \ Testing.checkEquals(FormattedH:try(123).formatted(),"123")+  \ FormattedH:try(123).formatted() `Matches:with` CheckValue:equals("123") }  unittest nonFormattedValue {-  \ Testing.checkEquals(FormattedH:try(String.builder()).formatted(),"[Append<Formatted>&Build<String>]{?}")+  \ FormattedH:try(String.builder()).formatted() `Matches:with` CheckValue:equals("[Append<Formatted>&Build<String>]{?}") }
lib/util/test/input.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -17,20 +17,20 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "TextReader checks" {-  success+  success TestChecker }  concrete Helper {-  @type checkNext (TextReader,String) -> ()+  @type checkNext (TextReader, String) -> () }  define Helper {-  checkNext (reader,line) {+  checkNext (reader, line) {     if (reader.pastEnd()) {       fail("past end")     }     String value <- reader.readNextLine()-    \ Testing.checkEquals(value,line)+    \ value `Matches:with` CheckValue:equals(line)   } } @@ -70,11 +70,11 @@  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")+    \ 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")     }@@ -85,15 +85,15 @@  unittest readAll {   String allContents <- TextReader.readAll(FakeFile.create())-  \ Testing.checkEquals(allContents,"this is a partial line\nwith some more data\nand\nmore lines\nunfinished")+  \ allContents `Matches:with` CheckValue:equals("this is a partial line\nwith some more data\nand\nmore lines\nunfinished") }   testcase "stdin is empty in tests" {-  success+  success TestChecker   timeout 1 }  unittest test {-  \ Testing.checkEquals(TextReader.readAll(BasicInput.stdin()),"")+  \ TextReader.readAll(BasicInput.stdin()) `Matches:with` CheckValue:equals("") }
lib/util/test/mutex.0rt view
@@ -32,7 +32,7 @@   testcase "MutexLock crashes if not freed" {-  crash+  failure   require "not freed" } @@ -43,7 +43,7 @@   testcase "MutexLock crashes if freed twice" {-  crash+  failure   require "freed multiple times" } 
lib/util/test/output.0rt view
@@ -47,7 +47,7 @@   testcase "error writer" {-  crash+  failure   require "message1"   require "message2"   require "message3"
lib/util/test/parse.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,213 +17,213 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "ParseChars tests" {-  success+  success TestChecker }  unittest floatNoDecimal {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("123"),122.9,123.1)+  \ ParseChars.float("123") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.0)) }  unittest floatDecimalLeft {-  \ UtilTesting.checkSuccessBetween(ParseChars.float(".123"),0.1229,0.1231)+  \ ParseChars.float(".123") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(0.123)) }  unittest floatDecimalRight {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("123."),122.9,123.1)+  \ ParseChars.float("123.") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.0)) }  unittest floatDecimalMiddle {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("123.456"),123.4559,123.4561)+  \ ParseChars.float("123.456") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.456)) }  unittest floatLeadingTrailingZeros {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("000123.456000"),123.4559,123.4561)+  \ ParseChars.float("000123.456000") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.456)) }  unittest floatNegative {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("-123.456"),-123.4561,-123.4559)+  \ ParseChars.float("-123.456") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(-123.456)) }  unittest floatPositive {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("+123.456"),123.4559,123.4561)+  \ ParseChars.float("+123.456") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.456)) }  unittest floatNegativeDecimalLeft {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("-.456"),-0.4561,-0.4559)+  \ ParseChars.float("-.456") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(-0.456)) }  unittest floatExponentNoDecimal {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("123E5"),122.9E5,123.1E5)+  \ ParseChars.float("123E5") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.0E5)) }  unittest floatNegativeExponent {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("123E-5"),122.9E-5,123.1E-5)+  \ ParseChars.float("123E-5") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.0E-5)) }  unittest floatPositiveExponent {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("123E+5"),122.9E5,123.1E5)+  \ ParseChars.float("123E+5") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.0E5)) }  unittest floatExponentDecimalRight {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("123.E5"),122.9E5,123.1E5)+  \ ParseChars.float("123.E5") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.0E5)) }  unittest floatExponentDecimalLeft {-  \ UtilTesting.checkSuccessBetween(ParseChars.float(".123E5"),122.9E2,123.1E2)+  \ ParseChars.float(".123E5") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.0E2)) }  unittest floatExponentDecimalMiddle {-  \ UtilTesting.checkSuccessBetween(ParseChars.float("123.456E5"),123.4559E5,123.4561E5)+  \ ParseChars.float("123.456E5") `Matches:with` CheckErrorOr:value(CheckFloat:almostEquals(123.456E5)) }  unittest floatEmpty {-  \ UtilTesting.checkError(ParseChars.float(""))+  \ ParseChars.float("") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest floatNoDigits {-  \ UtilTesting.checkError(ParseChars.float("."))+  \ ParseChars.float(".") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest floatTwoDecimals {-  \ UtilTesting.checkError(ParseChars.float("1.1."))+  \ ParseChars.float("1.1.") `Matches:with` CheckErrorOr:error(CheckString:contains("failed")) }  unittest floatExponentNoDigitsNoDecimal {-  \ UtilTesting.checkError(ParseChars.float("E5"))+  \ ParseChars.float("E5") `Matches:with` CheckErrorOr:error(CheckString:contains("E")) }  unittest floatExponentNoDigitsDecimal {-  \ UtilTesting.checkError(ParseChars.float(".E5"))+  \ ParseChars.float(".E5") `Matches:with` CheckErrorOr:error(CheckString:contains("E")) }  unittest floatExponentNoDigitsSign {-  \ UtilTesting.checkError(ParseChars.float("-E5"))+  \ ParseChars.float("-E5") `Matches:with` CheckErrorOr:error(CheckString:contains("E")) }  unittest floatDecimalAfterExponent {-  \ UtilTesting.checkError(ParseChars.float("1E.5"))+  \ ParseChars.float("1E.5") `Matches:with` CheckErrorOr:error(CheckString:contains(".")) }  unittest floatExponentExcessData {-  \ UtilTesting.checkError(ParseChars.float("123E5Q"))+  \ ParseChars.float("123E5Q") `Matches:with` CheckErrorOr:error(CheckString:contains("failed")) }  unittest floatBadCharAfterDigit {-  \ UtilTesting.checkError(ParseChars.float("123X"))+  \ ParseChars.float("123X") `Matches:with` CheckErrorOr:error(CheckString:contains("failed")) }  unittest floatMissingExponentDigits {-  \ UtilTesting.checkError(ParseChars.float("123E"))+  \ ParseChars.float("123E") `Matches:with` CheckErrorOr:error(CheckString:contains("exponent")) }  unittest int {-  \ UtilTesting.checkSuccess(ParseChars.int("1234"),1234)+  \ ParseChars.int("1234") `Matches:with` CheckErrorOr:value(CheckValue:equals(1234)) }  unittest intNegative {-  \ UtilTesting.checkSuccess(ParseChars.int("-1234"),-1234)+  \ ParseChars.int("-1234") `Matches:with` CheckErrorOr:value(CheckValue:equals(-1234)) }  unittest intPositive {-  \ UtilTesting.checkSuccess(ParseChars.int("+1234"),1234)+  \ ParseChars.int("+1234") `Matches:with` CheckErrorOr:value(CheckValue:equals(1234)) }  unittest intLeadingZeros {-  \ UtilTesting.checkSuccess(ParseChars.int("001234"),1234)+  \ ParseChars.int("001234") `Matches:with` CheckErrorOr:value(CheckValue:equals(1234)) }  unittest intEmpty {-  \ UtilTesting.checkError(ParseChars.int(""))+  \ ParseChars.int("") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest intJustSign {-  \ UtilTesting.checkError(ParseChars.int("-"))+  \ ParseChars.int("-") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest intBadDigit {-  \ UtilTesting.checkError(ParseChars.int("12A"))+  \ ParseChars.int("12A") `Matches:with` CheckErrorOr:error(CheckString:contains("failed")) }  unittest hexInt {-  \ UtilTesting.checkSuccess(ParseChars.hexInt("12AbCdEf"),\x12ABCDEF)+  \ ParseChars.hexInt("12AbCdEf") `Matches:with` CheckErrorOr:value(CheckValue:equals(\x12ABCDEF)) }  unittest hexIntNegative {-  \ UtilTesting.checkSuccess(ParseChars.hexInt("-12AbCdEf"),-\x12ABCDEF)+  \ ParseChars.hexInt("-12AbCdEf") `Matches:with` CheckErrorOr:value(CheckValue:equals(-\x12ABCDEF)) }  unittest hexIntPositive {-  \ UtilTesting.checkSuccess(ParseChars.hexInt("+12AbCdEf"),\x12ABCDEF)+  \ ParseChars.hexInt("+12AbCdEf") `Matches:with` CheckErrorOr:value(CheckValue:equals(\x12ABCDEF)) }  unittest hexIntLeadingZeros {-  \ UtilTesting.checkSuccess(ParseChars.hexInt("0012AbCdEf"),\x12ABCDEF)+  \ ParseChars.hexInt("0012AbCdEf") `Matches:with` CheckErrorOr:value(CheckValue:equals(\x12ABCDEF)) }  unittest hexIntEmpty {-  \ UtilTesting.checkError(ParseChars.hexInt(""))+  \ ParseChars.hexInt("") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest hexIntJustSign {-  \ UtilTesting.checkError(ParseChars.hexInt("-"))+  \ ParseChars.hexInt("-") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest hexIntBadDigit {-  \ UtilTesting.checkError(ParseChars.hexInt("12Q"))+  \ ParseChars.hexInt("12Q") `Matches:with` CheckErrorOr:error(CheckString:contains("failed")) }  unittest octInt {-  \ UtilTesting.checkSuccess(ParseChars.octInt("127"),\o127)+  \ ParseChars.octInt("127") `Matches:with` CheckErrorOr:value(CheckValue:equals(\o127)) }  unittest octIntNegative {-  \ UtilTesting.checkSuccess(ParseChars.octInt("-127"),-\o127)+  \ ParseChars.octInt("-127") `Matches:with` CheckErrorOr:value(CheckValue:equals(-\o127)) }  unittest octIntPositive {-  \ UtilTesting.checkSuccess(ParseChars.octInt("+127"),\o127)+  \ ParseChars.octInt("+127") `Matches:with` CheckErrorOr:value(CheckValue:equals(\o127)) }  unittest octIntLeadingZeros {-  \ UtilTesting.checkSuccess(ParseChars.octInt("00127"),\o127)+  \ ParseChars.octInt("00127") `Matches:with` CheckErrorOr:value(CheckValue:equals(\o127)) }  unittest octIntEmpty {-  \ UtilTesting.checkError(ParseChars.octInt(""))+  \ ParseChars.octInt("") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest octIntJustSign {-  \ UtilTesting.checkError(ParseChars.octInt("-"))+  \ ParseChars.octInt("-") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest octIntBadDigit {-  \ UtilTesting.checkError(ParseChars.octInt("19"))+  \ ParseChars.octInt("19") `Matches:with` CheckErrorOr:error(CheckString:contains("failed")) }  unittest binInt {-  \ UtilTesting.checkSuccess(ParseChars.binInt("100101"),\b100101)+  \ ParseChars.binInt("100101") `Matches:with` CheckErrorOr:value(CheckValue:equals(\b100101)) }  unittest binIntNegative {-  \ UtilTesting.checkSuccess(ParseChars.binInt("-100101"),-\b100101)+  \ ParseChars.binInt("-100101") `Matches:with` CheckErrorOr:value(CheckValue:equals(-\b100101)) }  unittest binIntPositive {-  \ UtilTesting.checkSuccess(ParseChars.binInt("+100101"),\b100101)+  \ ParseChars.binInt("+100101") `Matches:with` CheckErrorOr:value(CheckValue:equals(\b100101)) }  unittest binIntLeadingZeros {-  \ UtilTesting.checkSuccess(ParseChars.binInt("00100101"),\b100101)+  \ ParseChars.binInt("00100101") `Matches:with` CheckErrorOr:value(CheckValue:equals(\b100101)) }  unittest binIntEmpty {-  \ UtilTesting.checkError(ParseChars.binInt(""))+  \ ParseChars.binInt("") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest binIntJustSign {-  \ UtilTesting.checkError(ParseChars.binInt("-"))+  \ ParseChars.binInt("-") `Matches:with` CheckErrorOr:error(CheckString:contains("missing digits")) }  unittest binIntBadDigit {-  \ UtilTesting.checkError(ParseChars.binInt("12"))+  \ ParseChars.binInt("12") `Matches:with` CheckErrorOr:error(CheckString:contains("failed")) }
lib/util/test/testing.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2023 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.@@ -16,81 +16,91 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -testcase "UtilTesting.checkError with error" {-  success+testcase "CheckErrorOr success" {+  success TestChecker } -unittest test {-  \ UtilTesting.checkError(ErrorOr:error("failure"))+unittest value {+  \ ErrorOr:value(123) `Matches:with` CheckErrorOr:value(CheckValue:equals(123)) } +unittest error {+  \ ErrorOr:error("something") `Matches:with` CheckErrorOr:error(CheckValue:equals("something"))+} -testcase "UtilTesting.checkError with value" {-  crash-  require "message"++testcase "CheckErrorOr:value failure with value" {+  failure TestChecker+  require "456"+  require "123" }  unittest test {-  \ UtilTesting.checkError(ErrorOr:value("message"))+  \ ErrorOr:value(456) `Matches:with` CheckErrorOr:value(CheckValue:equals(123)) }  -testcase "UtilTesting.checkSuccess success" {-  success+testcase "CheckErrorOr:value failure with error" {+  failure TestChecker+  require "something"+  require "123" }  unittest test {-  \ UtilTesting.checkSuccess(ErrorOr:value("message"),"message")+  \ ErrorOr:error("something") `Matches:with` CheckErrorOr:value(CheckValue:equals(123)) }  -testcase "UtilTesting.checkSuccess bad value" {-  crash-  require "message"-  require "foo"+testcase "CheckErrorOr:value failure with empty" {+  failure TestChecker+  require "empty"+  require "123" }  unittest test {-  \ UtilTesting.checkSuccess(ErrorOr:value("foo"),"message")+  \ empty `Matches:with` CheckErrorOr:value(CheckValue:equals(123)) }  -testcase "UtilTesting.checkSuccess with error" {-  crash-  require "message"-  require "failure"+testcase "CheckErrorOr:error failure with value" {+  failure TestChecker+  require "456"+  require "something" }  unittest test {-  \ UtilTesting.checkSuccess(ErrorOr:error("failure"),"message")+  \ ErrorOr:value(456) `Matches:with` CheckErrorOr:error(CheckValue:equals("something")) }  -testcase "UtilTesting.checkSuccessBetween success" {-  success+testcase "CheckErrorOr:error failure with error" {+  failure TestChecker+  require "message"+  require "something" }  unittest test {-  \ UtilTesting.checkSuccessBetween(ErrorOr:value(1),0,2)+  \ ErrorOr:error("message") `Matches:with` CheckErrorOr:error(CheckValue:equals("something")) }  -testcase "UtilTesting.checkSuccess bad value" {-  crash-  require "7.+0.*2"+testcase "CheckErrorOr:error failure with empty" {+  failure TestChecker+  require "empty"+  require "something" }  unittest test {-  \ UtilTesting.checkSuccessBetween(ErrorOr:value(7),0,2)+  \ empty `Matches:with` CheckErrorOr:error(CheckValue:equals("something")) }  -testcase "UtilTesting.checkSuccess with error" {-  crash-  require "0.*2"-  require "failure"+testcase "CheckErrorOr:error failure with non-Formatted" {+  failure TestChecker+  require "CharBuffer"+  require "something" }  unittest test {-  \ UtilTesting.checkSuccessBetween(ErrorOr:error("failure"),0,2)+  \ ErrorOr:value(CharBuffer.new(0)) `Matches:with` CheckErrorOr:error(CheckValue:equals("something")) }
lib/util/test/time.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -38,7 +38,7 @@   testcase "sleepSeconds() does not interfere with test timeout" {-  crash+  failure   require "signal 14"   timeout 1 }@@ -49,7 +49,7 @@   testcase "sleepSecondsPrecise() does not interfere with test timeout" {-  crash+  failure   require "signal 14"   timeout 1 }@@ -60,7 +60,7 @@   testcase "monoSeconds() diff is somewhat accurate" {-  success+  success TestChecker   timeout 2 } @@ -68,12 +68,12 @@   Float start <- Realtime.monoSeconds()   \ Realtime.sleepSeconds(0.5)   Float stop <- Realtime.monoSeconds()-  \ Testing.checkBetween(stop-start,0.5,0.6)+  \ (stop-start) `Matches:with` CheckValue:betweenEquals(0.5, 0.6) }  unittest testPrecise {   Float start <- Realtime.monoSeconds()   \ Realtime.sleepSecondsPrecise(0.5)   Float stop <- Realtime.monoSeconds()-  \ Testing.checkBetween(stop-start,0.5,0.51)+  \ (stop-start) `Matches:with` CheckValue:betweenEquals(0.5, 0.51) }
lib/util/testing.0rp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2023 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.@@ -16,35 +16,8 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -$TestsOnly$--// General lib/util helpers for use in unit tests.-concrete UtilTesting {-  // Check the value for an ErrorOr error. Crashes if it is not an error.-  //-  // Args:-  // - ErrorOr<Formatted>: Actual value.-  @type checkError (ErrorOr<Formatted>) -> ()--  // Check the values for equality. Crashes if they are not equal.-  //-  // Args:-  // - ErrorOr<#x>: Actual value.-  // - #x: Expected value.-  @type checkSuccess<#x>-    #x requires Formatted-    #x defines Equals<#x>-  (ErrorOr<#x>,#x) -> ()--  // Check that the value is within a range. Crashes if it is not in the range.-  //-  // Args:-  // - ErrorOr<#x>: Actual value.-  // - #x: Lower bound.-  // - #x: Upper bound.-  @type checkSuccessBetween<#x>-    #x requires Formatted-    #x defines Equals<#x>-    #x defines LessThan<#x>-  (ErrorOr<#x>,#x,#x) -> ()+// Checks the contents of an ErrorOr.+concrete CheckErrorOr<#x> {+  @category value<#x> (ValueMatcher<#x>) -> (ValueMatcher<ErrorOr<#x>>)+  @category error (ValueMatcher<String>) -> (ValueMatcher<ErrorOr<any>>) }
src/Cli/Compiler.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2020-2022 Kevin P. Barry+Copyright 2020-2023 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.@@ -49,7 +49,7 @@ import Module.ProcessMetadata import Parser.SourceFile import Parser.TextParser (SourceContext)-import Types.Builtin+import Types.Builtin (requiredStaticTypes) import Types.DefinedCategory import Types.TypeCategory import Types.TypeInstance@@ -288,7 +288,7 @@           let lf' = lf ++ getLinkFlagsForDeps deps2           let os     = getObjectFilesForDeps deps2           let ofr = getObjectFileResolver os-          let objects = ofr ns2 req+          let objects = ofr ns2 (req `Set.union` requiredStaticTypes)           return $ CompileToBinary mainAbs objects [] f0 paths2 lf'         getCommand LinkDynamic mainAbs f0 deps2 paths2 = do           let objects = getLibrariesForDeps deps2@@ -316,16 +316,16 @@ createModuleTemplates resolver p d ds cm deps1 deps2 = do   time <- errorFromIO getCurrentTime   (ps,xs,_) <- findSourceFiles p (d:ds)-  (LanguageModule _ _ _ cs0 ps0 ts0 cs1 ps1 ts1 _ _) <-+  (LanguageModule _ _ _ cs0 ps0 tc0 tp0 cs1 ps1 tc1 tp1 _ _ cm0) <-     fmap (createLanguageModule [] Map.empty . fst) $ loadModuleGlobals resolver p (PublicNamespace,PrivateNamespace) ps Nothing deps1 deps2   xs' <- zipWithContents resolver p xs   ds2 <- mapCompilerM parseInternalSource xs'   let ds3 = concat $ map (\(_,_,d2) -> d2) ds2-  tm <- foldM includeNewTypes defaultCategories [cs0,cs1,ps0,ps1,ts0,ts1]-  let cs = filter isValueConcrete $ cs1++ps1++ts1+  tm <- foldM includeNewTypes cm0 [cs0,cs1,ps0,ps1,tc0,tp0,tc1,tp1]+  let cs = filter isValueConcrete $ cs1++ps1++tc1++tp1   let ca = Set.fromList $ map getCategoryName $ filter isValueConcrete cs   let ca' = foldr Set.delete ca $ map dcName ds3-  let testingCats = Set.fromList $ map getCategoryName ts1+  let testingCats = Set.fromList $ (map getCategoryName tc1) ++ (map getCategoryName tp1)   ts <- fmap concat $ mapCompilerM (\n -> generate (n `Set.member` testingCats) tm n) $ Set.toList ca'   mapCompilerM_ (writeTemplate time) ts where     generate testing tm n = do@@ -376,18 +376,22 @@   [WithVisibility (AnyCategory c)] -> LanguageModule c createLanguageModule ss em cs = lm where   lm = LanguageModule {-      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],-      lmPublicLocal       = map wvData $ apply cs [without FromDependency,without ModuleOnly,without TestsOnly],-      lmPrivateLocal      = map wvData $ apply cs [without FromDependency,with    ModuleOnly,without TestsOnly],-      lmTestingLocal      = map wvData $ apply cs [without FromDependency,with TestsOnly],+      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],+      lmPublicTestingDeps   = map wvData $ apply cs [with    FromDependency,without ModuleOnly,with TestsOnly],+      lmPrivateTestingDeps  = map wvData $ apply cs [with    FromDependency,with    ModuleOnly,with TestsOnly],+      lmPublicLocal         = map wvData $ apply cs [without FromDependency,without ModuleOnly,without TestsOnly],+      lmPrivateLocal        = map wvData $ apply cs [without FromDependency,with    ModuleOnly,without TestsOnly],+      lmPublicTestingLocal  = map wvData $ apply cs [without FromDependency,without ModuleOnly,with TestsOnly],+      lmPrivateTestingLocal = map wvData $ apply cs [without FromDependency,with    ModuleOnly,with TestsOnly],       lmStreamlined = ss,-      lmExprMap  = em+      lmExprMap  = em,+      lmEmptyCategories = CategoryMap km Map.empty     }+  km = Map.fromList $ map (\(WithVisibility _ t) -> (getCategoryName t,getCategoryContext t)) cs   ns = map (mapCodeVisibility getCategoryNamespace) cs   with    v = hasCodeVisibility v   without v = not . hasCodeVisibility v
src/Cli/ParseCompileOptions.hs view
@@ -25,6 +25,7 @@ import Control.Monad (when) import Lens.Micro import Text.Regex.TDFA+import qualified Data.Set as Set  import Base.CompilerError import Cli.CompileOptions@@ -85,9 +86,9 @@     "",     "Options:",     "  -f: Force an operation that zeolite would otherwise reject.",-    "  -j [# parallel]: Parallel execution of compilation subprocesses.",     "  -i [module]: A single source module to include as a public dependency.",     "  -I [module]: A single source module to include as a private dependency.",+    "  -j [# parallel]: Parallel execution of compilation subprocesses.",     "  -o [binary]: The name of the binary file to create with -m.",     "  -p [path]: Set a path prefix for finding modules or files.",     "  --log-traces [filename]: Log call traces to a file when running tests.",@@ -124,8 +125,19 @@ defaultMainFunc :: String defaultMainFunc = "run" +optionsWithArgs :: Set.Set Char+optionsWithArgs = Set.fromList "iIjmop"++splitOptionClusters :: [String] -> [String]+splitOptionClusters (o@('-':c:rest):os)+  | c == '-' || null rest          = o : splitOptionClusters os+  | c `Set.member` optionsWithArgs = ('-':c:[]) : rest : splitOptionClusters os+  | otherwise                      = ('-':c:[]) : splitOptionClusters (('-':rest):os)+splitOptionClusters (o:os) = o : splitOptionClusters os+splitOptionClusters [] = []+ parseCompileOptions :: CollectErrorsM m => [String] -> m CompileOptions-parseCompileOptions = parseAll emptyCompileOptions . zip ([1..] :: [Int]) where+parseCompileOptions = parseAll emptyCompileOptions . zip ([1..] :: [Int]) . splitOptionClusters where   parseAll co [] = return co   parseAll co os = do     (os',co') <- parseSingle co os
src/Cli/RunCompiler.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2020-2021 Kevin P. Barry+Copyright 2020-2021,2023 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.@@ -203,9 +203,9 @@     sequence_ $ intercalate [string_ ","] $ map ((:[]) . parseColTitle) tracesLogHeader     some (char '\n' <|> char '\r') >> return ()   parseSingle = do-    ms <- parseDec+    ms <- fmap snd parseDec     string_ ","-    pid <- parseDec+    pid <- fmap snd parseDec     string_ ","     func <- quotedString     string_ ","
src/Cli/TestRunner.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2020-2021 Kevin P. Barry+Copyright 2020-2021,2023 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.@@ -108,7 +108,7 @@              Just  t -> compilerWarningM $ "Explicit timeouts are ignored in " ++ ex2 ++ " tests: " ++ show t      run (ExpectCompilerError _ rs es) _ _ cs ds ts = do-      result <- toTrackedErrors $ compileAll [] cs ds ts+      result <- toTrackedErrors $ compileAll Nothing [] cs ds ts       if not $ isCompilerError result          then compilerErrorM "Expected compilation failure"          else fmap (:[]) $ return $ do@@ -117,22 +117,22 @@            checkContent rs es (lines warnings ++ lines errors) [] []      run (ExpectCompiles _ rs es) _ _ cs ds ts = do-      result <- toTrackedErrors $ compileAll [] cs ds ts+      result <- toTrackedErrors $ compileAll Nothing [] cs ds ts       if isCompilerError result          then fromTrackedErrors result >> return []          else fmap (:[]) $ return $ do            let warnings = show $ getCompilerWarnings result            checkContent rs es (lines warnings) [] [] -    run (ExpectRuntimeError _ rs es) args timeout cs ds ts = do-      when (length ts /= 1) $ compilerErrorM "Exactly one unittest is required when crash is expected"+    run (ExpectRuntimeError _ t rs es) args timeout cs ds ts = do+      when (length ts /= 1) $ compilerErrorM "Exactly one unittest is required when failure is expected"       uniqueTestNames ts-      execute False rs es args timeout cs ds ts+      execute False t rs es args timeout cs ds ts -    run (ExpectRuntimeSuccess _ rs es) args timeout cs ds ts = do+    run (ExpectRuntimeSuccess _ t rs es) args timeout cs ds ts = do       when (null ts) $ compilerErrorM "At least one unittest is required when success is expected"       uniqueTestNames ts-      execute True rs es args timeout cs ds ts+      execute True t rs es args timeout cs ds ts      checkContent rs es comp err out = do       let cr = checkRequired rs comp err out@@ -157,8 +157,8 @@     testClash (n,ts) = "unittest " ++ show n ++ " is defined multiple times" !!>       (mapCompilerM_ (compilerErrorM . ("Defined at " ++) . formatFullContext) $ sort $ map tpContext ts) -    execute s2 rs es args timeout cs ds ts = do-      result <- toTrackedErrors $ compileAll args cs ds ts+    execute s2 t rs es args timeout cs ds ts = do+      result <- toTrackedErrors $ compileAll t args cs ds ts       if isCompilerError result          then return [result >> return ()]          else do@@ -185,10 +185,10 @@             (hPutStrLn stderr $ "--- unittest " ++ show f2 ++ " passed ---")             (hPutStrLn stderr $ "--- unittest " ++ show f2 ++ " failed ---") -    compileAll args cs ds ts = do+    compileAll t args cs ds ts = do       let ns1 = StaticNamespace $ privateNamespace s       let cs' = map (setCategoryNamespace ns1) cs-      fromTrackedErrors $ compileTestsModule cm ns1 args cs' ds ts+      fromTrackedErrors $ compileTestsModule cm ns1 args t cs' ds ts      checkRequired rs comp err out = mapCompilerM_ (checkSubsetForRegex True  comp err out) rs     checkExcluded es comp err out = mapCompilerM_ (checkSubsetForRegex False comp err out) es
src/Compilation/CompilerState.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -48,6 +48,7 @@   csCheckVariableInit,   csClearOutput,   csCurrentScope,+  csDelegateArgs,   csExprLookup,   csGetCategoryFunction,   csGetCleanup,@@ -55,6 +56,7 @@   csGetNoTrace,   csGetOutput,   csGetParamScope,+  csGetTestsOnly,   csGetTypeFunction,   csGetVariable,   csInheritDeferred,@@ -101,6 +103,7 @@  import Base.CompilerError import Base.GeneralType+import Base.Positional import Types.DefinedCategory import Types.Procedure import Types.TypeCategory@@ -150,9 +153,11 @@   ccReleaseExprMacro :: a -> [c] -> MacroName -> m a   ccSetNoTrace :: a -> Bool -> m a   ccGetNoTrace :: a -> m Bool+  ccGetTestsOnly :: a -> m Bool   ccAddTrace :: a -> String -> m a   ccGetTraces :: a -> m [String]   ccCanForward :: a -> [ParamName] -> [VariableName] -> m Bool+  ccDelegateArgs :: a -> m (Positional (Maybe (CallArgLabel c), VariableName))  data MemberValue c =   MemberValue {@@ -359,11 +364,17 @@ csGetNoTrace :: CompilerContext c m s a => CompilerState a m Bool csGetNoTrace = fmap ccGetNoTrace get >>= lift +csGetTestsOnly :: CompilerContext c m s a => CompilerState a m Bool+csGetTestsOnly = fmap ccGetTestsOnly get >>= lift+ csAddTrace :: CompilerContext c m s a => String -> CompilerState a m () csAddTrace t = fmap (\x -> ccAddTrace x t) get >>= lift >>= put  csCanForward :: CompilerContext c m s a => [ParamName] -> [VariableName] -> CompilerState a m Bool csCanForward ps as = fmap (\x -> ccCanForward x ps as) get >>= lift++csDelegateArgs :: CompilerContext c m s a => CompilerState a m (Positional (Maybe (CallArgLabel c), VariableName))+csDelegateArgs = fmap ccDelegateArgs get >>= lift  data CompiledData s =   CompiledData {
src/Compilation/ProcedureContext.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -89,8 +89,9 @@     _pcExprMap :: ExprMap c,     _pcReservedMacros :: [(MacroName,[c])],     _pcNoTrace :: Bool,+    _pcTestsOnly :: Bool,     _pcTraces :: [String],-    _pcParentCall :: Maybe (Positional ParamName,Positional VariableName)+    _pcParentCall :: Maybe (Positional ParamName,Positional (Maybe (CallArgLabel c), InputValue c))   }  $(makeLenses ''ProcedureContext)@@ -146,7 +147,17 @@                  case t of                       Just t0 -> replaceSelfInstance self t0                       Nothing -> return self-    getFunction t' t' where+    f <- getFunction t' t'+    when (ctx ^. pcType /= sfType f && ctx ^. pcType /= CategoryNone) $+      "In call to " ++ show (sfName f) ++ formatFullContextBrace c ??> checkVisibility (ctx ^. pcScope) (sfVisibility f) f+    return f where+      checkVisibility _ FunctionVisibilityDefault _ = return ()+      checkVisibility CategoryScope v _ = "Function restricted to @type and @value contexts" ??> compilerErrorM (show v)+      checkVisibility _ _ f = do+        r <- ccResolver ctx+        allFilters <- ccAllFilters ctx+        self <- fmap (singleType . JustTypeInstance) $ ccSelfType ctx+        checkFunctionCallVisibility r allFilters f self       multipleMatchError t2 fs = do         "Multiple matches for function " ++ show n ++ " called on " ++ show t2 ++ formatFullContextBrace c !!>           mapErrorsM (map show fs)@@ -409,19 +420,28 @@   ccReleaseExprMacro ctx _ n = return $ ctx & pcReservedMacros %~ (filter ((/= n) . fst))   ccSetNoTrace ctx t = return $ ctx & pcNoTrace .~ t   ccGetNoTrace = return . (^. pcNoTrace)+  ccGetTestsOnly = return . (^. pcTestsOnly)   ccAddTrace ctx "" = return ctx   ccAddTrace ctx t = return $ ctx & pcTraces <>~ [t]   ccGetTraces = return . (^. pcTraces)   ccCanForward ctx ps as = handle (ctx ^. pcParentCall) where+    nameOrError (InputValue _ n) = return n+    nameOrError _                = emptyErrorM     handle Nothing = return False     handle (Just (ps0,as0)) = collectFirstM [checkMatch ps0 as0,return False]     checkMatch ps0 as0 = do+      as0' <- fmap Positional $ mapCompilerM (nameOrError . snd) $ pValues as0       processPairs_ equalOrError ps0 (Positional ps)-      processPairs_ equalOrError as0 (Positional as)+      processPairs_ equalOrError as0' (Positional as)       return True     equalOrError x y       | x == y    = return ()       | otherwise = emptyErrorM+  ccDelegateArgs ctx = handle (ctx ^. pcParentCall) where+    nameOrError (l,InputValue _ n) = return (l,n)+    nameOrError (_,DiscardInput c) = compilerErrorM $ "Delegation is not allowed with ignored args" ++ formatFullContextBrace c+    handle Nothing = compilerErrorM "Delegation is only allowed within function calls"+    handle (Just (_,as0)) = fmap Positional $ mapCompilerM nameOrError $ pValues as0  updateReturnVariables :: (Show c, CollectErrorsM m) =>   (Map.Map VariableName (VariableValue c)) ->@@ -444,17 +464,25 @@  updateArgVariables :: (Show c, CollectErrorsM m) =>   (Map.Map VariableName (VariableValue c)) ->-  Positional (PassedValue c) -> ArgValues c ->+  Positional (PassedValue c, Maybe (CallArgLabel c)) -> ArgValues c ->   m (Map.Map VariableName (VariableValue c)) updateArgVariables ma as1 as2 = do   as <- processPairs alwaysPair as1 (avNames as2)   let as' = filter (not . isDiscardedInput . snd) as   foldM update ma as' where-    update va (PassedValue _ t,a) = do+    checkName (Just l) (InputValue c (VariableName n))+      | l `matchesCallArgLabel` n = return ()+      | otherwise = compilerWarningM $ "Variable " ++ n +++                                         formatFullContextBrace c +++                                         " has a different name than arg label " ++ show l+    checkName _ _ = return ()+    update va ((PassedValue _ t,n),a) = do       let c = ivContext a       case ivName a `Map.lookup` va of-            Nothing -> return $ Map.insert (ivName a) (VariableValue c LocalScope t (VariableReadOnly c)) va+            Nothing -> return ()             (Just v) -> compilerErrorM $ "Variable " ++ show (ivName a) ++                                          formatFullContextBrace c ++                                          " is already defined" ++                                          formatFullContextBrace (vvContext v)+      checkName n a+      return $ Map.insert (ivName a) (VariableValue c LocalScope t (VariableReadOnly c)) va
src/CompilerCxx/CategoryContext.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -42,9 +42,9 @@   getContextForInit :: (Show c, CollectErrorsM m) =>-  CategoryMap c -> ExprMap c -> AnyCategory c -> DefinedCategory c ->+  Bool -> CategoryMap c -> ExprMap c -> AnyCategory c -> DefinedCategory c ->   SymbolScope -> m (ProcedureContext c)-getContextForInit tm em t d s = do+getContextForInit to tm em t d s = do   let ps = Positional $ getCategoryParams t   -- NOTE: This is always ValueScope for initializer checks.   let ms = filter ((== ValueScope) . dmScope) $ dcMembers d@@ -85,14 +85,15 @@       _pcExprMap = em,       _pcReservedMacros = [],       _pcNoTrace = False,+      _pcTestsOnly = to,       _pcTraces = [],       _pcParentCall = Nothing     }  getProcedureContext :: (Show c, CollectErrorsM m) =>-  ScopeContext c -> ScopedFunction c -> ExecutableProcedure c -> m (ProcedureContext c)-getProcedureContext (ScopeContext tm t ps ms pa fa va em)-                    ff@(ScopedFunction _ _ _ s as1 rs1 ps1 fs _)+  Bool -> ScopeContext c -> ScopedFunction c -> ExecutableProcedure c -> m (ProcedureContext c)+getProcedureContext to (ScopeContext tm t ps ms pa fa va em)+                    ff@(ScopedFunction _ _ _ s _ as1 rs1 ps1 fs _)                     (ExecutableProcedure _ _ _ _ as2 rs2 _) = do   rs' <- if isUnnamedReturns rs2             then return $ ValidatePositions rs1@@ -146,21 +147,17 @@       _pcExprMap = em,       _pcReservedMacros = [],       _pcNoTrace = False,+      _pcTestsOnly = to,       _pcTraces = [],       _pcParentCall = parentCall     }   where     pairOutput (PassedValue c1 t2) (OutputValue c2 n2) = return $ (n2,PassedValue (c2++c1) t2)-    psList = map vpParam $ pValues ps1-    asList = sequence $ map maybeArgName $ pValues $ avNames as2-    maybeArgName (InputValue _ n) = Just n-    maybeArgName _                = Nothing-    parentCall = case asList of-                      Just as3 -> Just (Positional psList,Positional as3)-                      Nothing  -> Nothing+    args = Positional $ zip (map snd $ pValues as1) (pValues $ avNames as2)+    parentCall = Just (fmap vpParam ps1,args) -getMainContext :: CollectErrorsM m => CategoryMap c -> ExprMap c -> m (ProcedureContext c)-getMainContext tm em = return $ ProcedureContext {+getMainContext :: CollectErrorsM m => Bool -> CategoryMap c -> ExprMap c -> m (ProcedureContext c)+getMainContext to tm em = return $ ProcedureContext {     _pcScope = LocalScope,     _pcType = CategoryNone,     _pcExtParams = Positional [],@@ -186,6 +183,7 @@     _pcExprMap = em,     _pcReservedMacros = [],     _pcNoTrace = False,+    _pcTestsOnly = to,     _pcTraces = [],     _pcParentCall = Nothing   }
src/CompilerCxx/Code.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -125,21 +125,23 @@ showCreationTrace = "TRACE_CREATION"  hasPrimitiveValue :: CategoryName -> Bool-hasPrimitiveValue BuiltinBool    = True-hasPrimitiveValue BuiltinInt     = True-hasPrimitiveValue BuiltinFloat   = True-hasPrimitiveValue BuiltinChar    = True-hasPrimitiveValue BuiltinPointer = True-hasPrimitiveValue _              = False+hasPrimitiveValue BuiltinBool       = True+hasPrimitiveValue BuiltinInt        = True+hasPrimitiveValue BuiltinFloat      = True+hasPrimitiveValue BuiltinChar       = True+hasPrimitiveValue BuiltinPointer    = True+hasPrimitiveValue BuiltinIdentifier = True+hasPrimitiveValue _                 = False  isStoredUnboxed :: ValueType -> Bool isStoredUnboxed t-  | t == boolRequiredValue    = True-  | t == intRequiredValue     = True-  | t == floatRequiredValue   = True-  | t == charRequiredValue    = True-  | isPointerRequiredValue t = True-  | otherwise                 = False+  | t == boolRequiredValue      = True+  | t == intRequiredValue       = True+  | t == floatRequiredValue     = True+  | t == charRequiredValue      = True+  | isPointerRequiredValue t    = True+  | isIdentifierRequiredValue t = True+  | otherwise                   = False  expressionFromLiteral :: PrimitiveType -> String -> (ExpressionType,ExpressionValue) expressionFromLiteral PrimString e =@@ -153,13 +155,14 @@ expressionFromLiteral PrimBool e =   (Positional [boolRequiredValue],UnboxedPrimitive PrimBool e) expressionFromLiteral PrimPointer _ = undefined+expressionFromLiteral PrimIdentifier _ = undefined  getFromLazy :: ExpressionValue -> ExpressionValue-getFromLazy (OpaqueMulti e)        = OpaqueMulti $ e ++ ".Get()"-getFromLazy (WrappedSingle e)      = WrappedSingle $ e ++ ".Get()"-getFromLazy (UnwrappedSingle e)    = UnwrappedSingle $ e ++ ".Get()"-getFromLazy (BoxedPrimitive t e)   = BoxedPrimitive t $ e ++ ".Get()"-getFromLazy (UnboxedPrimitive t e) = UnboxedPrimitive t  $ e ++ ".Get()"+getFromLazy (OpaqueMulti e)        = OpaqueMulti $ "(" ++ e ++ ").Get()"+getFromLazy (WrappedSingle e)      = WrappedSingle $ "(" ++ e ++ ").Get()"+getFromLazy (UnwrappedSingle e)    = UnwrappedSingle $ "(" ++ e ++ ").Get()"+getFromLazy (BoxedPrimitive t e)   = BoxedPrimitive t $ "(" ++ e ++ ").Get()"+getFromLazy (UnboxedPrimitive t e) = UnboxedPrimitive t  $ "(" ++ e ++ ").Get()" getFromLazy (LazySingle e)         = LazySingle $ getFromLazy e  useAsWhatever :: ExpressionValue -> String@@ -171,147 +174,162 @@ useAsWhatever (LazySingle e)         = useAsWhatever $ getFromLazy e  useAsReturns :: ExpressionValue -> String-useAsReturns (OpaqueMulti e)                  = e-useAsReturns (WrappedSingle e)                = "ReturnTuple(" ++ e ++ ")"-useAsReturns (UnwrappedSingle e)              = "ReturnTuple(" ++ e ++ ")"-useAsReturns (BoxedPrimitive PrimBool e)      = "ReturnTuple(Box_Bool(" ++ e ++ "))"-useAsReturns (BoxedPrimitive PrimString e)    = "ReturnTuple(Box_String(" ++ e ++ "))"-useAsReturns (BoxedPrimitive PrimChar e)      = "ReturnTuple(Box_Char(" ++ e ++ "))"-useAsReturns (BoxedPrimitive PrimInt e)       = "ReturnTuple(Box_Int(" ++ e ++ "))"-useAsReturns (BoxedPrimitive PrimFloat e)     = "ReturnTuple(Box_Float(" ++ e ++ "))"-useAsReturns (BoxedPrimitive PrimPointer e)   = "ReturnTuple(Box_Pointer<void>(" ++ e ++ "))"-useAsReturns (UnboxedPrimitive PrimBool e)    = "ReturnTuple(Box_Bool(" ++ e ++ "))"-useAsReturns (UnboxedPrimitive PrimString e)  = "ReturnTuple(Box_String(" ++ e ++ "))"-useAsReturns (UnboxedPrimitive PrimChar e)    = "ReturnTuple(Box_Char(" ++ e ++ "))"-useAsReturns (UnboxedPrimitive PrimInt e)     = "ReturnTuple(Box_Int(" ++ e ++ "))"-useAsReturns (UnboxedPrimitive PrimFloat e)   = "ReturnTuple(Box_Float(" ++ e ++ "))"-useAsReturns (UnboxedPrimitive PrimPointer e) = "ReturnTuple(Box_Pointer<void>(" ++ e ++ "))"-useAsReturns (LazySingle e)                   = useAsReturns $ getFromLazy e+useAsReturns (OpaqueMulti e)                     = e+useAsReturns (WrappedSingle e)                   = "ReturnTuple(" ++ e ++ ")"+useAsReturns (UnwrappedSingle e)                 = "ReturnTuple(" ++ e ++ ")"+useAsReturns (BoxedPrimitive PrimBool e)         = "ReturnTuple(Box_Bool(" ++ e ++ "))"+useAsReturns (BoxedPrimitive PrimString e)       = "ReturnTuple(Box_String(" ++ e ++ "))"+useAsReturns (BoxedPrimitive PrimChar e)         = "ReturnTuple(Box_Char(" ++ e ++ "))"+useAsReturns (BoxedPrimitive PrimInt e)          = "ReturnTuple(Box_Int(" ++ e ++ "))"+useAsReturns (BoxedPrimitive PrimFloat e)        = "ReturnTuple(Box_Float(" ++ e ++ "))"+useAsReturns (BoxedPrimitive PrimPointer e)      = "ReturnTuple(Box_Pointer<void>(" ++ e ++ "))"+useAsReturns (BoxedPrimitive PrimIdentifier e)   = "ReturnTuple(Box_Identifier(" ++ e ++ "))"+useAsReturns (UnboxedPrimitive PrimBool e)       = "ReturnTuple(Box_Bool(" ++ e ++ "))"+useAsReturns (UnboxedPrimitive PrimString e)     = "ReturnTuple(Box_String(" ++ e ++ "))"+useAsReturns (UnboxedPrimitive PrimChar e)       = "ReturnTuple(Box_Char(" ++ e ++ "))"+useAsReturns (UnboxedPrimitive PrimInt e)        = "ReturnTuple(Box_Int(" ++ e ++ "))"+useAsReturns (UnboxedPrimitive PrimFloat e)      = "ReturnTuple(Box_Float(" ++ e ++ "))"+useAsReturns (UnboxedPrimitive PrimPointer e)    = "ReturnTuple(Box_Pointer<void>(" ++ e ++ "))"+useAsReturns (UnboxedPrimitive PrimIdentifier e) = "ReturnTuple(Box_Identifier(" ++ e ++ "))"+useAsReturns (LazySingle e)                      = useAsReturns $ getFromLazy e  useAsArgs :: ExpressionValue -> String-useAsArgs (OpaqueMulti e)                  = e-useAsArgs (WrappedSingle e)                = e-useAsArgs (UnwrappedSingle e)              = e-useAsArgs (BoxedPrimitive PrimBool e)      = "Box_Bool(" ++ e ++ ")"-useAsArgs (BoxedPrimitive PrimString e)    = "Box_String(" ++ e ++ ")"-useAsArgs (BoxedPrimitive PrimChar e)      = "Box_Char(" ++ e ++ ")"-useAsArgs (BoxedPrimitive PrimInt e)       = "Box_Int(" ++ e ++ ")"-useAsArgs (BoxedPrimitive PrimFloat e)     = "Box_Float(" ++ e ++ ")"-useAsArgs (BoxedPrimitive PrimPointer e)   = "Box_Pointer<void>(" ++ e ++ ")"-useAsArgs (UnboxedPrimitive PrimBool e)    = "Box_Bool(" ++ e ++ ")"-useAsArgs (UnboxedPrimitive PrimString e)  = "Box_String(" ++ e ++ ")"-useAsArgs (UnboxedPrimitive PrimChar e)    = "Box_Char(" ++ e ++ ")"-useAsArgs (UnboxedPrimitive PrimInt e)     = "Box_Int(" ++ e ++ ")"-useAsArgs (UnboxedPrimitive PrimFloat e)   = "Box_Float(" ++ e ++ ")"-useAsArgs (UnboxedPrimitive PrimPointer e) = "Box_Pointer<void>(" ++ e ++ ")"-useAsArgs (LazySingle e)                   = useAsArgs $ getFromLazy e+useAsArgs (OpaqueMulti e)                     = e+useAsArgs (WrappedSingle e)                   = e+useAsArgs (UnwrappedSingle e)                 = e+useAsArgs (BoxedPrimitive PrimBool e)         = "Box_Bool(" ++ e ++ ")"+useAsArgs (BoxedPrimitive PrimString e)       = "Box_String(" ++ e ++ ")"+useAsArgs (BoxedPrimitive PrimChar e)         = "Box_Char(" ++ e ++ ")"+useAsArgs (BoxedPrimitive PrimInt e)          = "Box_Int(" ++ e ++ ")"+useAsArgs (BoxedPrimitive PrimFloat e)        = "Box_Float(" ++ e ++ ")"+useAsArgs (BoxedPrimitive PrimPointer e)      = "Box_Pointer<void>(" ++ e ++ ")"+useAsArgs (BoxedPrimitive PrimIdentifier e)   = "Box_Identifier(" ++ e ++ ")"+useAsArgs (UnboxedPrimitive PrimBool e)       = "Box_Bool(" ++ e ++ ")"+useAsArgs (UnboxedPrimitive PrimString e)     = "Box_String(" ++ e ++ ")"+useAsArgs (UnboxedPrimitive PrimChar e)       = "Box_Char(" ++ e ++ ")"+useAsArgs (UnboxedPrimitive PrimInt e)        = "Box_Int(" ++ e ++ ")"+useAsArgs (UnboxedPrimitive PrimFloat e)      = "Box_Float(" ++ e ++ ")"+useAsArgs (UnboxedPrimitive PrimPointer e)    = "Box_Pointer<void>(" ++ e ++ ")"+useAsArgs (UnboxedPrimitive PrimIdentifier e) = "Box_Identifier(" ++ e ++ ")"+useAsArgs (LazySingle e)                      = useAsArgs $ getFromLazy e  useAsUnwrapped :: ExpressionValue -> String-useAsUnwrapped (OpaqueMulti e)                  = "(" ++ e ++ ").At(0)"-useAsUnwrapped (WrappedSingle e)                = e-useAsUnwrapped (UnwrappedSingle e)              = e-useAsUnwrapped (BoxedPrimitive PrimBool e)      = "Box_Bool(" ++ e ++ ")"-useAsUnwrapped (BoxedPrimitive PrimString e)    = "Box_String(" ++ e ++ ")"-useAsUnwrapped (BoxedPrimitive PrimChar e)      = "Box_Char(" ++ e ++ ")"-useAsUnwrapped (BoxedPrimitive PrimInt e)       = "Box_Int(" ++ e ++ ")"-useAsUnwrapped (BoxedPrimitive PrimFloat e)     = "Box_Float(" ++ e ++ ")"-useAsUnwrapped (BoxedPrimitive PrimPointer e)   = "Box_Pointer<void>(" ++ e ++ ")"-useAsUnwrapped (UnboxedPrimitive PrimBool e)    = "Box_Bool(" ++ e ++ ")"-useAsUnwrapped (UnboxedPrimitive PrimString e)  = "Box_String(" ++ e ++ ")"-useAsUnwrapped (UnboxedPrimitive PrimChar e)    = "Box_Char(" ++ e ++ ")"-useAsUnwrapped (UnboxedPrimitive PrimInt e)     = "Box_Int(" ++ e ++ ")"-useAsUnwrapped (UnboxedPrimitive PrimFloat e)   = "Box_Float(" ++ e ++ ")"-useAsUnwrapped (UnboxedPrimitive PrimPointer e) = "Box_Pointer<void>(" ++ e ++ ")"-useAsUnwrapped (LazySingle e)                   = useAsUnwrapped $ getFromLazy e+useAsUnwrapped (OpaqueMulti e)                     = "(" ++ e ++ ").At(0)"+useAsUnwrapped (WrappedSingle e)                   = e+useAsUnwrapped (UnwrappedSingle e)                 = e+useAsUnwrapped (BoxedPrimitive PrimBool e)         = "Box_Bool(" ++ e ++ ")"+useAsUnwrapped (BoxedPrimitive PrimString e)       = "Box_String(" ++ e ++ ")"+useAsUnwrapped (BoxedPrimitive PrimChar e)         = "Box_Char(" ++ e ++ ")"+useAsUnwrapped (BoxedPrimitive PrimInt e)          = "Box_Int(" ++ e ++ ")"+useAsUnwrapped (BoxedPrimitive PrimFloat e)        = "Box_Float(" ++ e ++ ")"+useAsUnwrapped (BoxedPrimitive PrimPointer e)      = "Box_Pointer<void>(" ++ e ++ ")"+useAsUnwrapped (BoxedPrimitive PrimIdentifier e)   = "Box_Identifier(" ++ e ++ ")"+useAsUnwrapped (UnboxedPrimitive PrimBool e)       = "Box_Bool(" ++ e ++ ")"+useAsUnwrapped (UnboxedPrimitive PrimString e)     = "Box_String(" ++ e ++ ")"+useAsUnwrapped (UnboxedPrimitive PrimChar e)       = "Box_Char(" ++ e ++ ")"+useAsUnwrapped (UnboxedPrimitive PrimInt e)        = "Box_Int(" ++ e ++ ")"+useAsUnwrapped (UnboxedPrimitive PrimFloat e)      = "Box_Float(" ++ e ++ ")"+useAsUnwrapped (UnboxedPrimitive PrimPointer e)    = "Box_Pointer<void>(" ++ e ++ ")"+useAsUnwrapped (UnboxedPrimitive PrimIdentifier e) = "Box_Identifier(" ++ e ++ ")"+useAsUnwrapped (LazySingle e)                      = useAsUnwrapped $ getFromLazy e  useAsUnboxed :: PrimitiveType -> ExpressionValue -> String-useAsUnboxed PrimBool    (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsBool()"-useAsUnboxed PrimString  (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsString()"-useAsUnboxed PrimChar    (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsChar()"-useAsUnboxed PrimInt     (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsInt()"-useAsUnboxed PrimFloat   (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsFloat()"-useAsUnboxed PrimPointer (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsPointer<OpaqueObject>()"-useAsUnboxed PrimBool    (WrappedSingle e)   = "(" ++ e ++ ").AsBool()"-useAsUnboxed PrimString  (WrappedSingle e)   = "(" ++ e ++ ").AsString()"-useAsUnboxed PrimChar    (WrappedSingle e)   = "(" ++ e ++ ").AsChar()"-useAsUnboxed PrimInt     (WrappedSingle e)   = "(" ++ e ++ ").AsInt()"-useAsUnboxed PrimFloat   (WrappedSingle e)   = "(" ++ e ++ ").AsFloat()"-useAsUnboxed PrimPointer (WrappedSingle e)   = "(" ++ e ++ ").AsPointer<OpaqueObject>()"-useAsUnboxed PrimBool    (UnwrappedSingle e) = "(" ++ e ++ ").AsBool()"-useAsUnboxed PrimString  (UnwrappedSingle e) = "(" ++ e ++ ").AsString()"-useAsUnboxed PrimChar    (UnwrappedSingle e) = "(" ++ e ++ ").AsChar()"-useAsUnboxed PrimInt     (UnwrappedSingle e) = "(" ++ e ++ ").AsInt()"-useAsUnboxed PrimFloat   (UnwrappedSingle e) = "(" ++ e ++ ").AsFloat()"-useAsUnboxed PrimPointer (UnwrappedSingle e) = "(" ++ e ++ ").AsPointer<OpaqueObject>()"-useAsUnboxed _ (BoxedPrimitive _ e)         = e-useAsUnboxed _ (UnboxedPrimitive _ e)       = e-useAsUnboxed t (LazySingle e)               = useAsUnboxed t $ getFromLazy e+useAsUnboxed PrimBool       (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsBool()"+useAsUnboxed PrimString     (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsString()"+useAsUnboxed PrimChar       (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsChar()"+useAsUnboxed PrimInt        (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsInt()"+useAsUnboxed PrimFloat      (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsFloat()"+useAsUnboxed PrimPointer    (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsPointer<OpaqueObject>()"+useAsUnboxed PrimIdentifier (OpaqueMulti e)     = "(" ++ e ++ ").At(0).AsIdentifier()"+useAsUnboxed PrimBool       (WrappedSingle e)   = "(" ++ e ++ ").AsBool()"+useAsUnboxed PrimString     (WrappedSingle e)   = "(" ++ e ++ ").AsString()"+useAsUnboxed PrimChar       (WrappedSingle e)   = "(" ++ e ++ ").AsChar()"+useAsUnboxed PrimInt        (WrappedSingle e)   = "(" ++ e ++ ").AsInt()"+useAsUnboxed PrimFloat      (WrappedSingle e)   = "(" ++ e ++ ").AsFloat()"+useAsUnboxed PrimPointer    (WrappedSingle e)   = "(" ++ e ++ ").AsPointer<OpaqueObject>()"+useAsUnboxed PrimIdentifier (WrappedSingle e)   = "(" ++ e ++ ").AsIdentifier()"+useAsUnboxed PrimBool       (UnwrappedSingle e) = "(" ++ e ++ ").AsBool()"+useAsUnboxed PrimString     (UnwrappedSingle e) = "(" ++ e ++ ").AsString()"+useAsUnboxed PrimChar       (UnwrappedSingle e) = "(" ++ e ++ ").AsChar()"+useAsUnboxed PrimInt        (UnwrappedSingle e) = "(" ++ e ++ ").AsInt()"+useAsUnboxed PrimFloat      (UnwrappedSingle e) = "(" ++ e ++ ").AsFloat()"+useAsUnboxed PrimPointer    (UnwrappedSingle e) = "(" ++ e ++ ").AsPointer<OpaqueObject>()"+useAsUnboxed PrimIdentifier (UnwrappedSingle e) = "(" ++ e ++ ").AsIdentifier()"+useAsUnboxed _ (BoxedPrimitive _ e)             = e+useAsUnboxed _ (UnboxedPrimitive _ e)           = e+useAsUnboxed t (LazySingle e)                   = useAsUnboxed t $ getFromLazy e  valueAsWrapped :: ExpressionValue -> ExpressionValue-valueAsWrapped (UnwrappedSingle e)              = WrappedSingle e-valueAsWrapped (BoxedPrimitive _ e)             = WrappedSingle e-valueAsWrapped (UnboxedPrimitive PrimBool e)    = WrappedSingle $ "Box_Bool(" ++ e ++ ")"-valueAsWrapped (UnboxedPrimitive PrimString e)  = WrappedSingle $ "Box_String(" ++ e ++ ")"-valueAsWrapped (UnboxedPrimitive PrimChar e)    = WrappedSingle $ "Box_Char(" ++ e ++ ")"-valueAsWrapped (UnboxedPrimitive PrimInt e)     = WrappedSingle $ "Box_Int(" ++ e ++ ")"-valueAsWrapped (UnboxedPrimitive PrimFloat e)   = WrappedSingle $ "Box_Float(" ++ e ++ ")"-valueAsWrapped (UnboxedPrimitive PrimPointer e) = WrappedSingle $ "Box_Pointer<void>(" ++ e ++ ")"-valueAsWrapped (LazySingle e)                   = valueAsWrapped $ getFromLazy e-valueAsWrapped v                                = v+valueAsWrapped (UnwrappedSingle e)                 = WrappedSingle e+valueAsWrapped (BoxedPrimitive _ e)                = WrappedSingle e+valueAsWrapped (UnboxedPrimitive PrimBool e)       = WrappedSingle $ "Box_Bool(" ++ e ++ ")"+valueAsWrapped (UnboxedPrimitive PrimString e)     = WrappedSingle $ "Box_String(" ++ e ++ ")"+valueAsWrapped (UnboxedPrimitive PrimChar e)       = WrappedSingle $ "Box_Char(" ++ e ++ ")"+valueAsWrapped (UnboxedPrimitive PrimInt e)        = WrappedSingle $ "Box_Int(" ++ e ++ ")"+valueAsWrapped (UnboxedPrimitive PrimFloat e)      = WrappedSingle $ "Box_Float(" ++ e ++ ")"+valueAsWrapped (UnboxedPrimitive PrimPointer e)    = WrappedSingle $ "Box_Pointer<void>(" ++ e ++ ")"+valueAsWrapped (UnboxedPrimitive PrimIdentifier e) = WrappedSingle $ "Box_Identifier(" ++ e ++ ")"+valueAsWrapped (LazySingle e)                      = valueAsWrapped $ getFromLazy e+valueAsWrapped v                                   = v  valueAsUnwrapped :: ExpressionValue -> ExpressionValue-valueAsUnwrapped (OpaqueMulti e)                  = UnwrappedSingle $ "(" ++ e ++ ").At(0)"-valueAsUnwrapped (WrappedSingle e)                = UnwrappedSingle e-valueAsUnwrapped (UnboxedPrimitive PrimBool e)    = UnwrappedSingle $ "Box_Bool(" ++ e ++ ")"-valueAsUnwrapped (UnboxedPrimitive PrimString e)  = UnwrappedSingle $ "Box_String(" ++ e ++ ")"-valueAsUnwrapped (UnboxedPrimitive PrimChar e)    = UnwrappedSingle $ "Box_Char(" ++ e ++ ")"-valueAsUnwrapped (UnboxedPrimitive PrimInt e)     = UnwrappedSingle $ "Box_Int(" ++ e ++ ")"-valueAsUnwrapped (UnboxedPrimitive PrimFloat e)   = UnwrappedSingle $ "Box_Float(" ++ e ++ ")"-valueAsUnwrapped (UnboxedPrimitive PrimPointer e) = UnwrappedSingle $ "Box_Pointer<void>(" ++ e ++ ")"-valueAsUnwrapped (LazySingle e)                   = valueAsUnwrapped $ getFromLazy e-valueAsUnwrapped v                                = v+valueAsUnwrapped (OpaqueMulti e)                     = UnwrappedSingle $ "(" ++ e ++ ").At(0)"+valueAsUnwrapped (WrappedSingle e)                   = UnwrappedSingle e+valueAsUnwrapped (UnboxedPrimitive PrimBool e)       = UnwrappedSingle $ "Box_Bool(" ++ e ++ ")"+valueAsUnwrapped (UnboxedPrimitive PrimString e)     = UnwrappedSingle $ "Box_String(" ++ e ++ ")"+valueAsUnwrapped (UnboxedPrimitive PrimChar e)       = UnwrappedSingle $ "Box_Char(" ++ e ++ ")"+valueAsUnwrapped (UnboxedPrimitive PrimInt e)        = UnwrappedSingle $ "Box_Int(" ++ e ++ ")"+valueAsUnwrapped (UnboxedPrimitive PrimFloat e)      = UnwrappedSingle $ "Box_Float(" ++ e ++ ")"+valueAsUnwrapped (UnboxedPrimitive PrimPointer e)    = UnwrappedSingle $ "Box_Pointer<void>(" ++ e ++ ")"+valueAsUnwrapped (UnboxedPrimitive PrimIdentifier e) = UnwrappedSingle $ "Box_Identifier(" ++ e ++ ")"+valueAsUnwrapped (LazySingle e)                      = valueAsUnwrapped $ getFromLazy e+valueAsUnwrapped v                                   = v  variableStoredType :: ValueType -> String variableStoredType t-  | t == boolRequiredValue   = "PrimBool"-  | t == intRequiredValue    = "PrimInt"-  | t == floatRequiredValue  = "PrimFloat"-  | t == charRequiredValue   = "PrimChar"-  | isPointerRequiredValue t = "PrimPointer"-  | isWeakValue t            = "WeakValue"-  | otherwise                = "BoxedValue"+  | t == boolRequiredValue      = "PrimBool"+  | t == intRequiredValue       = "PrimInt"+  | t == floatRequiredValue     = "PrimFloat"+  | t == charRequiredValue      = "PrimChar"+  | isPointerRequiredValue t    = "PrimPointer"+  | isIdentifierRequiredValue t = "PrimIdentifier"+  | isWeakValue t               = "WeakValue"+  | otherwise                   = "BoxedValue"  variableLazyType :: ValueType -> String variableLazyType t = "LazyInit<" ++ variableStoredType t ++ ">"  variableProxyType :: ValueType -> String variableProxyType t-  | t == boolRequiredValue   = "PrimBool"-  | t == intRequiredValue    = "PrimInt"-  | t == floatRequiredValue  = "PrimFloat"-  | t == charRequiredValue   = "PrimChar"-  | isPointerRequiredValue t = "PrimPointer"-  | isWeakValue t            = "WeakValue&"-  | otherwise                = "BoxedValue&"+  | t == boolRequiredValue      = "PrimBool"+  | t == intRequiredValue       = "PrimInt"+  | t == floatRequiredValue     = "PrimFloat"+  | t == charRequiredValue      = "PrimChar"+  | isPointerRequiredValue t    = "PrimPointer"+  | isIdentifierRequiredValue t = "PrimIdentifier"+  | isWeakValue t               = "WeakValue&"+  | otherwise                   = "BoxedValue&"  readStoredVariable :: Bool -> ValueType -> String -> ExpressionValue readStoredVariable True t s = LazySingle $ readStoredVariable False t s readStoredVariable False t s-  | t == boolRequiredValue   = UnboxedPrimitive PrimBool    s-  | t == intRequiredValue    = UnboxedPrimitive PrimInt     s-  | t == floatRequiredValue  = UnboxedPrimitive PrimFloat   s-  | t == charRequiredValue   = UnboxedPrimitive PrimChar    s-  | isPointerRequiredValue t = UnboxedPrimitive PrimPointer s-  | otherwise                = UnwrappedSingle s+  | t == boolRequiredValue      = UnboxedPrimitive PrimBool     s+  | t == intRequiredValue       = UnboxedPrimitive PrimInt      s+  | t == floatRequiredValue     = UnboxedPrimitive PrimFloat    s+  | t == charRequiredValue      = UnboxedPrimitive PrimChar     s+  | isPointerRequiredValue t    = UnboxedPrimitive PrimPointer  s+  | isIdentifierRequiredValue t = UnboxedPrimitive PrimIdentifier s+  | otherwise                   = UnwrappedSingle s  writeStoredVariable :: ValueType -> ExpressionValue -> String writeStoredVariable t e-  | t == boolRequiredValue   = useAsUnboxed PrimBool    e-  | t == intRequiredValue    = useAsUnboxed PrimInt     e-  | t == floatRequiredValue  = useAsUnboxed PrimFloat   e-  | t == charRequiredValue   = useAsUnboxed PrimChar    e-  | isPointerRequiredValue t = useAsUnboxed PrimPointer e-  | otherwise                = useAsUnwrapped e+  | t == boolRequiredValue      = useAsUnboxed PrimBool     e+  | t == intRequiredValue       = useAsUnboxed PrimInt      e+  | t == floatRequiredValue     = useAsUnboxed PrimFloat    e+  | t == charRequiredValue      = useAsUnboxed PrimChar     e+  | isPointerRequiredValue t    = useAsUnboxed PrimPointer  e+  | isIdentifierRequiredValue t = useAsUnboxed PrimIdentifier e+  | otherwise                   = useAsUnwrapped e  functionLabelType :: ScopedFunction c -> String functionLabelType = getType . sfScope where
src/CompilerCxx/CxxFiles.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -592,7 +592,7 @@     createParam p = onlyCode $ paramType ++ " " ++ paramName (vpParam p) ++ ";"    inlineCategoryConstructor t d tm em = do-    ctx <- getContextForInit tm em t d CategoryScope+    ctx <- getContextForInit testing tm em t d CategoryScope     initMembers <- runDataCompiler (sequence $ map compileLazyInit members) ctx     let initMembersStr = intercalate ", " $ cdOutput initMembers     let initColon = if null initMembersStr then "" else " : "@@ -709,20 +709,22 @@       "CycleCheck<" ++ n2 ++ "> marker(*this);"     ] -  defineProcedure t = compileExecutableProcedure (isImmutable t)+  defineProcedure t = compileExecutableProcedure testing (isImmutable t)   declareProcedure t = procedureDeclaration (isImmutable t)  isImmutable :: AnyCategory c -> Bool isImmutable = any isCategoryImmutable . getCategoryPragmas  formatFunctionTypes :: Show c => ScopedFunction c -> [String]-formatFunctionTypes (ScopedFunction c _ _ s as rs ps fa _) = [location,args,returns,params] ++ filters where+formatFunctionTypes (ScopedFunction c _ _ s _ as rs ps fa _) = [location,args,returns,params] ++ filters where   location = show s ++ " function declared at " ++ formatFullContext c-  args    = "Arg Types:    (" ++ intercalate ", " (map (show . pvType) $ pValues as)  ++ ")"+  args    = "Arg Types:    (" ++ intercalate ", " (map singleArg $ pValues as)  ++ ")"   returns = "Return Types: (" ++ intercalate ", " (map (show . pvType) $ pValues rs)  ++ ")"   params  = "Type Params:  <" ++ intercalate ", " (map (show . vpParam) $ pValues ps) ++ ">"   filters = map singleFilter fa   singleFilter (ParamFilter _ n2 f) = "  " ++ show n2 ++ " " ++ show f+  singleArg (a,Just n) = show (pvType a) ++ " " ++ (calName n)+  singleArg (a,_)      = show (pvType a)  createMainCommon :: String -> CompiledData [String] -> CompiledData [String] -> [String] createMainCommon n (CompiledData req0 _ out0) (CompiledData req1 _ out1) =@@ -747,13 +749,17 @@     argv = onlyCode "ProgramArgv program_argv(argc, argv);"  generateTestFile :: (Ord c, Show c, CollectErrorsM m) =>-  CategoryMap c -> ExprMap c  -> [String] -> [TestProcedure c] -> m (CompiledData [String])-generateTestFile tm em args ts = "In the creation of the test binary procedure" ??> do+  CategoryMap c -> ExprMap c  -> [String] -> Maybe ([c],TypeInstance) -> [TestProcedure c] ->+  m (CompiledData [String])+generateTestFile tm em args t ts = "In the creation of the test binary procedure" ??> do+  wrap <- case t of+               Just t2 -> compileWrapTestcase tm t2+               Nothing -> return emptyCode   ts' <- fmap mconcat $ mapCompilerM (compileTestProcedure tm em) ts   (include,sel) <- selectTestFromArgv1 $ map tpName ts   let (CompiledData req traces _) = ts' <> sel   let contentTop = mconcat [timeoutInclude,onlyCodes include,ts']-  let contentMain = mconcat [setTimeout,argv,callLog,sel]+  let contentMain = mconcat [setTimeout,argv,callLog,wrap,sel]   let file = testsOnlySourceGuard ++ createMainCommon "testcase" contentTop contentMain   return $ CompiledData req traces file where     args' = map escapeChars args@@ -1032,8 +1038,8 @@   fromDefines ds = Set.toList $ Set.unions $ map (categoriesFromDefine . vdType) ds   fromDefine (DefinesInstance d ps) = d:(fromGenerals $ pValues ps)   fromFunctions fs = concat $ map fromFunction fs-  fromFunction (ScopedFunction _ _ t2 _ as rs _ fs _) =-    [t2] ++ (fromGenerals $ map (vtType . pvType) (pValues as ++ pValues rs)) ++ fromFilters fs+  fromFunction (ScopedFunction _ _ t2 _ _ as rs _ fs _) =+    [t2] ++ (fromGenerals $ map (vtType . pvType) (map fst (pValues as) ++ pValues rs)) ++ fromFilters fs   fromFilters fs = concat $ map (fromFilter . pfFilter) fs   fromFilter (TypeFilter _ t2)  = Set.toList $ categoriesFromTypes t2   fromFilter (DefinesFilter t2) = fromDefine t2
src/CompilerCxx/LanguageModule.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -35,7 +35,6 @@ import CompilerCxx.CxxFiles import CompilerCxx.Naming import Module.CompileMetadata (CategorySpec(..))-import Types.Builtin import Types.DefinedCategory import Types.Procedure import Types.TypeCategory@@ -49,12 +48,15 @@     lmLocalNamespaces :: Set.Set Namespace,     lmPublicDeps :: [AnyCategory c],     lmPrivateDeps :: [AnyCategory c],-    lmTestingDeps :: [AnyCategory c],+    lmPublicTestingDeps :: [AnyCategory c],+    lmPrivateTestingDeps :: [AnyCategory c],     lmPublicLocal :: [AnyCategory c],     lmPrivateLocal :: [AnyCategory c],-    lmTestingLocal :: [AnyCategory c],+    lmPublicTestingLocal :: [AnyCategory c],+    lmPrivateTestingLocal :: [AnyCategory c],     lmStreamlined :: [CategoryName],-    lmExprMap :: ExprMap c+    lmExprMap :: ExprMap c,+    lmEmptyCategories :: CategoryMap c   }  data PrivateSource c =@@ -68,47 +70,49 @@ compileLanguageModule :: (Ord c, Show c, CollectErrorsM m) =>   LanguageModule c -> Map.Map CategoryName (CategorySpec c) ->   [PrivateSource c] -> m [CxxOutput]-compileLanguageModule (LanguageModule ns0 ns1 ns2 cs0 ps0 ts0 cs1 ps1 ts1  ss em) cm xa = do+compileLanguageModule (LanguageModule ns0 ns1 ns2 cs0 ps0 tc0 tp0 cs1 ps1 tc1 tp1 ss em cm0) sm xa = do   let dm = mapDefByName $ concat $ map psDefine xa-  checkDefined dm extensions allExternal $ filter isValueConcrete (cs1 ++ ps1 ++ ts1)+  checkDefined dm extensions allExternal $ filter isValueConcrete (cs1 ++ ps1 ++ tc1 ++ tp1)   checkSupefluous $ Set.toList $ extensions `Set.difference` ca-  tmPublic  <- foldM includeNewTypes defaultCategories [cs0,cs1]-  tmPrivate <- foldM includeNewTypes tmPublic          [ps0,ps1]-  tmTesting <- foldM includeNewTypes tmPrivate         [ts0,ts1]+  tmPublic         <- foldM includeNewTypes cm0             [cs0,cs1]+  tmPrivate        <- foldM includeNewTypes tmPublic        [ps0,ps1]+  tmPublicTesting  <- foldM includeNewTypes tmPublic        [tc0,tc1]+  tmPrivateTesting <- foldM includeNewTypes tmPublicTesting [ps0,tp0,ps1,tp1]   xxInterfaces <- fmap concat $ collectAllM $     map (generateNativeInterface False nsPublic)  (onlyNativeInterfaces cs1) ++     map (generateNativeInterface False nsPrivate) (onlyNativeInterfaces ps1) ++-    map (generateNativeInterface True  nsPrivate) (onlyNativeInterfaces ts1)-  xxPrivate <- fmap concat $ mapCompilerM (compilePrivate tmPrivate tmTesting) xa-  xxStreamlined <- fmap concat $ mapCompilerM (streamlined tmPrivate tmTesting) $ nub ss+    map (generateNativeInterface True  nsPublic)  (onlyNativeInterfaces tc1) +++    map (generateNativeInterface True  nsPrivate) (onlyNativeInterfaces tp1)+  xxPrivate <- fmap concat $ mapCompilerM (compilePrivate tmPrivate tmPrivateTesting) xa+  xxStreamlined <- fmap concat $ mapCompilerM (streamlined tmPrivate tmPrivateTesting) $ nub ss   let allFiles = xxInterfaces ++ xxPrivate ++ xxStreamlined   noDuplicateFiles $ map (\f -> (coFilename f,coNamespace f)) allFiles   return allFiles where     nsPublic  = ns0 `Set.union` ns2     nsPrivate = ns1 `Set.union` nsPublic     extensions = Set.fromList ss-    allExternal = Set.unions [extensions,Map.keysSet cm]-    testingCats = Set.fromList $ map getCategoryName ts1+    allExternal = Set.unions [extensions,Map.keysSet sm]+    testingCats = Set.fromList $ (map getCategoryName tc1) ++ (map getCategoryName tp1)     onlyNativeInterfaces = filter (not . (`Set.member` extensions) . getCategoryName) . filter (not . isValueConcrete)-    localCats = Set.fromList $ map getCategoryName $ cs1 ++ ps1 ++ ts1+    localCats = Set.fromList $ map getCategoryName $ cs1 ++ ps1 ++ tc1 ++ tp1     streamlined tm0 tm2 n = do       checkLocal localCats ([] :: [String]) n       let testing = n `Set.member` testingCats       let tm = if testing then tm2 else tm0       (_,t) <- getConcreteCategory tm ([],n)       let ctx = FileContext testing tm nsPrivate Map.empty-      let spec = Map.findWithDefault (CategorySpec [] [] []) (getCategoryName t) cm+      let spec = Map.findWithDefault (CategorySpec [] [] []) (getCategoryName t) sm       generateStreamlinedExtension ctx t spec     compilePrivate tmPrivate tmTesting (PrivateSource ns3 testing cs2 ds) = do       let tm = if testing                   then tmTesting                   else tmPrivate       let cs = Set.fromList $ map getCategoryName $ if testing-                                                       then cs2 ++ cs1 ++ ps1 ++ ts1+                                                       then cs2 ++ cs1 ++ ps1 ++ tc1 ++ tp1                                                        else cs2 ++ cs1 ++ ps1       tm' <- includeNewTypes tm cs2       let ctx = FileContext testing tm' (ns3 `Set.insert` nsPrivate) em-      checkLocals ds $ Map.keysSet tm'+      checkLocals ds $ Map.keysSet $ cmAvailable tm'       when testing $ checkTests ds (cs1 ++ ps1)       let dm = mapDefByName ds       checkDefined dm Set.empty Set.empty $ filter isValueConcrete cs2@@ -123,7 +127,7 @@       checkLocal cs (dcContext d) (dcName d)       fmap snd $ getConcreteCategory tm (dcContext d,dcName d)     mapDefByName = Map.fromListWith (++) . map (\d -> (dcName d,[d]))-    ca = Set.fromList $ map getCategoryName $ filter isValueConcrete (cs1 ++ ps1 ++ ts1)+    ca = Set.fromList $ map getCategoryName $ filter isValueConcrete (cs1 ++ ps1 ++ tc1 ++ tp1)     checkLocals ds tm = mapCompilerM_ (\d -> checkLocal tm (dcContext d) (dcName d)) ds     checkLocal cs2 c n =       when (not $ n `Set.member` cs2) $@@ -170,9 +174,9 @@       return $ (f,ns3) `Set.insert` used  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+  LanguageModule c -> Namespace -> [String] -> Maybe ([c],TypeInstance) -> [AnyCategory c] ->+  [DefinedCategory c] -> [TestProcedure c] -> m ([CxxOutput],CxxOutput,[(FunctionName,[c])])+compileTestsModule cm ns args t cs ds ts = do   let xs = PrivateSource {       psNamespace = ns,       psTesting = True,@@ -180,23 +184,23 @@       psDefine = ds     }   xx <- compileLanguageModule cm Map.empty [xs]-  (main,fs) <- compileTestMain cm args xs ts+  (main,fs) <- compileTestMain cm args t xs ts   return (xx,main,fs)  compileTestMain :: (Ord c, Show c, CollectErrorsM m) =>-  LanguageModule c -> [String] -> PrivateSource c -> [TestProcedure c] ->+  LanguageModule c -> [String] -> Maybe ([c],TypeInstance) -> PrivateSource c -> [TestProcedure c] ->   m (CxxOutput,[(FunctionName,[c])])-compileTestMain (LanguageModule ns0 ns1 ns2 cs0 ps0 ts0 cs1 ps1 ts1 _ em) args ts2 tests = do+compileTestMain (LanguageModule ns0 ns1 ns2 cs0 ps0 tc0 tp0 cs1 ps1 tc1 tp1 _ em cm0) args t ts2 tests = do   tm' <- tm-  (CompiledData req traces main) <- generateTestFile tm' em args tests+  (CompiledData req traces main) <- generateTestFile tm' em args t tests   let output = CxxOutput Nothing testFilename NoNamespace (psNamespace ts2 `Set.insert` Set.unions [ns0,ns1,ns2]) req traces main-  let tests' = map (\t -> (tpName t,tpContext t)) tests+  let tests' = map (\t2 -> (tpName t2,tpContext t2)) tests   return (output,tests') where-  tm = foldM includeNewTypes defaultCategories [cs0,cs1,ps0,ps1,ts0,ts1,psCategory ts2]+  tm = foldM includeNewTypes cm0 [cs0,cs1,ps0,ps1,tc0,tp0,tc1,tp1,psCategory ts2]  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+compileModuleMain (LanguageModule ns0 ns1 ns2 cs0 ps0 _ _ cs1 ps1 _ _ _ em cm0) xa n f = do   let resolved = filter (\d -> dcName d == n) $ concat $ map psDefine $ filter (not . psTesting) xa   reconcile resolved   tm' <- tm@@ -204,7 +208,7 @@   tm'' <- includeNewTypes tm' cs   (ns,main) <- generateMainFile tm'' em n f   return $ CxxOutput Nothing mainFilename NoNamespace (ns `Set.insert` Set.unions [ns0,ns1,ns2]) (Set.fromList [n]) Set.empty main where-    tm = foldM includeNewTypes defaultCategories [cs0,cs1,ps0,ps1]+    tm = foldM includeNewTypes cm0 [cs0,cs1,ps0,ps1]     reconcile [_] = return ()     reconcile []  = compilerErrorM $ "No matches for main category " ++ show n ++ " ($TestsOnly$ sources excluded)"     reconcile ds  =
src/CompilerCxx/Procedure.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -31,6 +31,7 @@   compileLazyInit,   compileRegularInit,   compileTestProcedure,+  compileWrapTestcase,   procedureDeclaration,   selectTestFromArgv1, ) where@@ -87,12 +88,12 @@   deriving Show  compileExecutableProcedure :: (Ord c, Show c, CollectErrorsM m) =>-  Bool -> CxxFunctionType -> ScopeContext c -> ScopedFunction c ->+  Bool -> Bool -> CxxFunctionType -> ScopeContext c -> ScopedFunction c ->   ExecutableProcedure c -> m (CompiledData [String])-compileExecutableProcedure immutable cxxType ctx-  ff@(ScopedFunction _ _ _ s as1 rs1 ps1 _ _)+compileExecutableProcedure to immutable cxxType ctx+  ff@(ScopedFunction _ _ _ s _ as1 rs1 ps1 _ _)   pp@(ExecutableProcedure c pragmas c2 n as2 rs2 p) = do-  ctx' <- getProcedureContext ctx ff pp+  ctx' <- getProcedureContext to ctx ff pp   output <- runDataCompiler compileWithReturn ctx'   procedureTrace <- setProcedureTrace   creationTrace  <- setCreationTrace@@ -152,7 +153,7 @@       | otherwise            = ["ReturnTuple returns(" ++ show (length $ pValues rs1) ++ ");"]     nameParams = flip map (zip ([0..] :: [Int]) $ pValues ps1) $       (\(i,p2) -> paramType ++ " " ++ paramName (vpParam p2) ++ " = params_args.GetParam(" ++ show i ++ ");")-    nameArgs = map nameSingleArg (zip ([0..] :: [Int]) $ zip (pValues as1) (pValues $ avNames as2))+    nameArgs = map nameSingleArg (zip ([0..] :: [Int]) $ zip (map fst $ pValues as1) (pValues $ avNames as2))     nameSingleArg (i,(t2,n2))       | isDiscardedInput n2 = "// Arg " ++ show i ++ " (" ++ show (pvType t2) ++ ") is discarded"       | otherwise = "const " ++ variableProxyType (pvType t2) ++ " " ++ variableName (ivName n2) ++@@ -307,6 +308,19 @@       csSetDeferred (UsedVariable c2 n)     createVariable (ExistingVariable (DiscardInput c2)) =       compilerErrorM $ "Cannot defer discarded value" ++ formatFullContextBrace c2+compileStatement (VariableSwap c vl vr) = message ??> handle vl vr where+  message = "In variable swap at " ++ formatFullContext c+  handle (OutputValue cl nl) (OutputValue cr nr) = do+    r <- csResolver+    fa <- csAllFilters+    (VariableValue _ sl tl _) <- getWritableVariable cl nl+    (VariableValue _ sr tr _) <- getWritableVariable cr nr+    lift $ checkValueAssignment r fa tl tr+    lift $ checkValueAssignment r fa tr tl+    csCheckVariableInit [UsedVariable cl nl, UsedVariable cr nr]+    scopedL <- autoScope sl+    scopedR <- autoScope sr+    csWrite ["SwapValues(" ++ scopedL ++ variableName nl ++ ", " ++ scopedR ++ variableName nr ++ ");"] compileStatement (Assignment c as e) = message ??> do   (ts,e') <- compileExpression e   r <- csResolver@@ -362,6 +376,9 @@       csWrite [scoped ++ variableName n ++ " = " ++                writeStoredVariable t (UnwrappedSingle $ "r.At(" ++ show i ++ ")") ++ ";"]     assignMulti _ = return ()+compileStatement (AssignmentEmpty c n e) = do+  (_,e') <- compileExpressionStart (InlineAssignment c n AssignIfEmpty e)+  csWrite ["(void) (" ++ useAsWhatever e' ++ ");"] compileStatement (NoValueExpression _ v) = compileVoidExpression v compileStatement (MarkReadOnly c vs) = mapM_ (\v -> csSetReadOnly (UsedVariable c v)) vs compileStatement (MarkHidden   c vs) = mapM_ (\v -> csSetHidden   (UsedVariable c v)) vs@@ -486,10 +503,10 @@                                                (Positional [t])   let currVar = hiddenVariableName $ VariableName "traverse"   let currType = orderOptionalValue $ fixTypeParams t2-  let currExpr    = BuiltinCall [] $ FunctionCall [] BuiltinRequire (Positional []) (Positional [RawExpression (Positional [currType]) (UnwrappedSingle currVar)])-  let currPresent = BuiltinCall [] $ FunctionCall [] BuiltinPresent (Positional []) (Positional [RawExpression (Positional [currType]) (UnwrappedSingle currVar)])-  let callNext = Expression c1 currExpr [ValueCall c1 $ FunctionCall c1 (FunctionName "next") (Positional []) (Positional [])]-  let callGet  = Expression c2 currExpr [ValueCall c2 $ FunctionCall c2 (FunctionName "get")  (Positional []) (Positional [])]+  let currExpr    = BuiltinCall [] $ FunctionCall [] BuiltinRequire (Positional []) (Positional [(Nothing,RawExpression (Positional [currType]) (UnwrappedSingle currVar))])+  let currPresent = BuiltinCall [] $ FunctionCall [] BuiltinPresent (Positional []) (Positional [(Nothing,RawExpression (Positional [currType]) (UnwrappedSingle currVar))])+  let callNext = Expression c1 currExpr [ValueCall c1 AlwaysCall $ FunctionCall c1 (FunctionName "next") (Positional []) (Positional [])]+  let callGet  = Expression c2 currExpr [ValueCall c2 AlwaysCall $ FunctionCall c2 (FunctionName "get")  (Positional []) (Positional [])]   (Positional [typeGet],exprNext) <- compileExpression callNext   when (typeGet /= currType) $ compilerErrorM $ "Unexpected return type from next(): " ++ show typeGet ++ " (expected) " ++ show currType ++ " (actual)"   let assnGet = if isAssignableDiscard a then [] else [Assignment c2 (Positional [a]) callGet]@@ -601,21 +618,31 @@                       CompilerContext c m [String] a) =>   Expression c -> CompilerState a m (ExpressionType,ExpressionValue) compileExpression = compile where+  callFunctionSpec c as (FunctionSpec _ (CategoryFunction c2 cn) fn ps) =+    compile (Expression c (CategoryCall c2 cn (FunctionCall c fn ps as)) [])+  callFunctionSpec c as (FunctionSpec _ (TypeFunction c2 tn) fn ps) =+    compile (Expression c (TypeCall c2 tn (FunctionCall c fn ps as)) [])+  callFunctionSpec c as (FunctionSpec _ (ValueFunction c2 e0) fn ps) =+    compile (Expression c (ParensExpression c2 e0) [ValueCall c AlwaysCall (FunctionCall c fn ps as)])+  callFunctionSpec c as (FunctionSpec c2 UnqualifiedFunction fn ps) =+    compile (Expression c (UnqualifiedCall c2 (FunctionCall c fn ps as)) [])   compile (Literal l) = compileValueLiteral l   compile (Expression _ s os) = do     foldl transform (compileExpressionStart s) os-  compile (UnaryExpression c (FunctionOperator _ (FunctionSpec _ (CategoryFunction c2 cn) fn ps)) e) =-    compile (Expression c (CategoryCall c2 cn (FunctionCall c fn ps (Positional [e]))) [])-  compile (UnaryExpression c (FunctionOperator _ (FunctionSpec _ (TypeFunction c2 tn) fn ps)) e) =-    compile (Expression c (TypeCall c2 tn (FunctionCall c fn ps (Positional [e]))) [])-  compile (UnaryExpression c (FunctionOperator _ (FunctionSpec _ (ValueFunction c2 e0) fn ps)) e) =-    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 (DelegatedFunctionCall c f) = "In function delegation at " ++ formatFullContext c ??> do+    args <- csDelegateArgs+    let vars = fmap (\(l,v) -> (l,Expression c (NamedVariable (OutputValue c v)) [])) args+    callFunctionSpec c vars f+  compile (DelegatedInitializeValue c t) = "In initialization delegation at " ++ formatFullContext c ??> do+    args <- csDelegateArgs+    let vars = fmap (\(_,v) -> Expression c (NamedVariable (OutputValue c v)) []) args+    compile (Expression c  (InitializeValue c t vars) [])+  compile (UnaryExpression c (FunctionOperator _ fa@(FunctionSpec _ _ _ _)) e) =+    callFunctionSpec c (Positional [(Nothing,e)]) fa   compile (UnaryExpression _ (NamedOperator c "-") (Literal (IntegerLiteral _ _ l))) =     compile (Literal (IntegerLiteral c False (-l)))-  compile (UnaryExpression _ (NamedOperator c "-") (Literal (DecimalLiteral _ l e))) =-    compile (Literal (DecimalLiteral c (-l) e))+  compile (UnaryExpression _ (NamedOperator c "-") (Literal (DecimalLiteral _ l e b))) =+    compile (Literal (DecimalLiteral c (-l) e b))   compile (UnaryExpression _ (NamedOperator c o) e) = do     (Positional ts,e') <- compileExpression e     t' <- requireSingle c ts@@ -645,13 +672,13 @@         | otherwise = compilerErrorM $ "Cannot use " ++ show t ++ " with unary ~ operator" ++                                        formatFullContextBrace c   compile (InfixExpression c e1 (FunctionOperator _ (FunctionSpec _ (CategoryFunction c2 cn) fn ps)) e2) =-    compile (Expression c (CategoryCall c2 cn (FunctionCall c fn ps (Positional [e1,e2]))) [])+    compile (Expression c (CategoryCall c2 cn (FunctionCall c fn ps (Positional [(Nothing,e1),(Nothing,e2)]))) [])   compile (InfixExpression c e1 (FunctionOperator _ (FunctionSpec _ (TypeFunction c2 tn) fn ps)) e2) =-    compile (Expression c (TypeCall c2 tn (FunctionCall c fn ps (Positional [e1,e2]))) [])+    compile (Expression c (TypeCall c2 tn (FunctionCall c fn ps (Positional [(Nothing,e1),(Nothing,e2)]))) [])   compile (InfixExpression c e1 (FunctionOperator _ (FunctionSpec _ (ValueFunction c2 e0) fn ps)) e2) =-    compile (Expression c (ParensExpression c2 e0) [ValueCall c (FunctionCall c fn ps (Positional [e1,e2]))])+    compile (Expression c (ParensExpression c2 e0) [ValueCall c AlwaysCall (FunctionCall c fn ps (Positional [(Nothing,e1),(Nothing,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 (Expression c (UnqualifiedCall c2 (FunctionCall c fn ps (Positional [(Nothing,e1),(Nothing,e2)]))) [])   compile (InfixExpression _ e1 (NamedOperator c o) e2) = do     e1' <- compileExpression e1     e2' <- if o `Set.member` logical@@ -679,6 +706,8 @@     bind t1' t2'     where       bind t1 t2+        | o `Set.member` comparison && isIdentifierRequiredValue t1 && isIdentifierRequiredValue t2 = do+          return (Positional [boolRequiredValue],glueInfix PrimIdentifier PrimBool e1 o e2)         | t1 /= t2 =           compilerErrorM $ "Cannot " ++ show o ++ " " ++ show t1 ++ " and " ++                            show t2 ++ formatFullContextBrace c@@ -726,11 +755,11 @@     (lift $ checkValueAssignment r fa t' vt) <??       "In explicit type conversion at " ++ formatFullContext c     return (Positional [vt],e')-  transform e (ValueCall c f) = do+  transform e (ValueCall c o f) = do     (Positional ts,e') <- e     t' <- requireSingle c ts-    f' <- lookupValueFunction t' f-    compileFunctionCall (Just $ useAsUnwrapped e') f' f+    f' <- lookupValueFunction t' o f+    compileFunctionCall (o == CallUnlessEmpty) (Just $ useAsUnwrapped e') f' f   transform e (SelectReturn c pos) = do     (Positional ts,e') <- e     when (not $ isOpaqueMulti e') $@@ -740,20 +769,37 @@     return (Positional [ts !! pos],WrappedSingle $ useAsReturns e' ++ ".At(" ++ show pos ++ ")")   requireSingle _ [t] = return t   requireSingle c2 ts =-    compilerErrorM $ "Function call requires 1 return but found but found {" ++-                            intercalate "," (map show ts) ++ "}" ++ formatFullContextBrace c2+    compilerErrorM $ "Function call requires one return but got " ++ formatTypes ts ++ formatFullContextBrace c2+  formatTypes [] = "none"+  formatTypes ts = intercalate ", " (map show ts) +forceOptionalReturns :: [c] -> ScopedFunction c -> ScopedFunction c+forceOptionalReturns c0 (ScopedFunction c n t s v as rs ps fs ms) =+  ScopedFunction c n t s v as rs' ps fs ms where+    rs' = fmap forceOptional rs+    forceOptional (PassedValue c2 (ValueType RequiredValue t2)) = (PassedValue (c0 ++ c2) (ValueType OptionalValue t2))+    forceOptional t2 = t2+ 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 _ _ _) =+  ValueType -> ValueCallType -> FunctionCall c -> CompilerState a m (ScopedFunction c)+lookupValueFunction (ValueType OptionalValue t) CallUnlessEmpty f@(FunctionCall c _ _ _) = do+  f' <- lookupValueFunction (ValueType RequiredValue t) AlwaysCall f+  return $ forceOptionalReturns c f'+lookupValueFunction t CallUnlessEmpty (FunctionCall c _ _ _) =+  compilerErrorM $ "Optional type required for &. but got " ++ show t ++ formatFullContextBrace c+lookupValueFunction (ValueType WeakValue t) _ (FunctionCall c _ _ _) =   compilerErrorM $ "Use strong to convert weak " ++ show t ++                         " to optional first" ++ formatFullContextBrace c-lookupValueFunction (ValueType OptionalValue t) (FunctionCall c _ _ _) =+lookupValueFunction (ValueType OptionalValue t) _ (FunctionCall c _ _ _) =   compilerErrorM $ "Use require to convert optional " ++ show t ++                         " to required first" ++ formatFullContextBrace c-lookupValueFunction (ValueType RequiredValue t) (FunctionCall c n _ _) =-  csGetTypeFunction c (Just t) n+lookupValueFunction (ValueType RequiredValue t) _ (FunctionCall c n _ _) = do+  f' <- csGetTypeFunction c (Just t) n+  when (sfScope f' /= ValueScope) $ compilerErrorM $ "Function " ++ show n +++                                                     " cannot be used as a value function" +++                                                     formatFullContextBrace c+  return f'  compileExpressionStart :: (Ord c, Show c, CollectErrorsM m,                            CompilerContext c m [String] a) =>@@ -773,11 +819,21 @@   -- NOTE: This will be skipped if expression compilation fails.   csReleaseExprMacro c n   return e'+compileExpressionStart (ExpressionMacro c MacroCallTrace) = do+  to <- csGetTestsOnly+  when (not to) $ compilerErrorM $ "$CallTrace$ is a $TestsOnly$ macro" ++ formatFullContextBrace c+  csAddRequired $ Set.fromList [BuiltinOrder,BuiltinFormatted]+  let formatted = singleType $ JustTypeInstance (TypeInstance BuiltinFormatted (Positional []))+  let order = singleType $ JustTypeInstance (TypeInstance BuiltinOrder (Positional [formatted]))+  nextFunc <- csGetTypeFunction c (Just order) (FunctionName "next")+  getFunc <- csGetTypeFunction c (Just order) (FunctionName "get")+  let getTrace = "GetCallTrace(" ++ functionName getFunc ++ ", " ++ functionName nextFunc ++ ")"+  return (Positional [orderOptionalValue formatted],UnwrappedSingle getTrace) compileExpressionStart (CategoryCall c t f@(FunctionCall _ n _ _)) = do   f' <- csGetCategoryFunction c (Just t) n   csAddRequired $ Set.fromList [t,sfType f']   t' <- expandCategory t-  compileFunctionCall (Just t') f' f+  compileFunctionCall False (Just t') f' f compileExpressionStart (TypeCall c t f@(FunctionCall _ n _ _)) = do   self <- autoSelfType   t' <- lift $ replaceSelfInstance self (singleType t)@@ -794,7 +850,7 @@   t2 <- if same            then return Nothing            else fmap Just $ expandGeneralInstance t'-  compileFunctionCall t2 f' f+  compileFunctionCall False t2 f' f   where     maybeSingleType = lift . tryCompilerM . matchOnlyLeaf     checkSame (Just (JustTypeInstance t2)) = csSameType t2@@ -803,7 +859,7 @@   ctx <- get   f' <- lift $ collectFirstM [tryCategory ctx,tryNonCategory ctx] <?? "In function call at " ++ formatFullContext c   csAddRequired $ Set.fromList [sfType f']-  compileFunctionCall Nothing f' f+  compileFunctionCall False Nothing f' f   where     tryCategory ctx = ccGetCategoryFunction ctx c Nothing n     tryNonCategory ctx = do@@ -819,7 +875,7 @@     compilerErrorM $ "Expected 0 type parameters" ++ formatFullContextBrace c   when (length (pValues es) /= 1) $     compilerErrorM $ "Expected 1 argument" ++ formatFullContextBrace c-  es' <- sequence $ map compileExpression $ pValues es+  es' <- sequence $ map (compileExpression . snd) $ pValues es   when (length (pValues $ fst $ head es') /= 1) $     compilerErrorM $ "Expected single return in argument" ++ formatFullContextBrace c   let (Positional [t0],e) = head es'@@ -827,12 +883,26 @@     compilerErrorM $ "Weak values not allowed here" ++ formatFullContextBrace c   return $ (Positional [boolRequiredValue],             UnboxedPrimitive PrimBool $ "BoxedValue::Present(" ++ useAsUnwrapped e ++ ")")+compileExpressionStart (BuiltinCall c (FunctionCall _ BuiltinIdentify ps es)) = do+  when (length (pValues ps) /= 0) $+    compilerErrorM $ "Expected 0 type parameters" ++ formatFullContextBrace c+  when (length (pValues es) /= 1) $+    compilerErrorM $ "Expected 1 argument" ++ formatFullContextBrace c+  es' <- sequence $ map (compileExpression . snd) $ pValues es+  when (length (pValues $ fst $ head es') /= 1) $+    compilerErrorM $ "Expected single return in argument" ++ formatFullContextBrace c+  let (Positional [t0],e) = head es'+  when (isWeakValue t0) $+    compilerErrorM $ "Weak values not allowed here" ++ formatFullContextBrace c+  csAddRequired $ Set.fromList [BuiltinIdentifier]+  return $ (Positional [ValueType RequiredValue (singleType $ JustTypeInstance (TypeInstance BuiltinIdentifier (Positional [(vtType t0)])))],+            UnboxedPrimitive PrimIdentifier $ "BoxedValue::Identify(" ++ useAsUnwrapped e ++ ")") compileExpressionStart (BuiltinCall c (FunctionCall _ BuiltinReduce ps es)) = do   when (length (pValues ps) /= 2) $     compilerErrorM $ "Expected 2 type parameters" ++ formatFullContextBrace c   when (length (pValues es) /= 1) $     compilerErrorM $ "Expected 1 argument" ++ formatFullContextBrace c-  es' <- sequence $ map compileExpression $ pValues es+  es' <- sequence $ map (compileExpression . snd) $ pValues es   when (length (pValues $ fst $ head es') /= 1) $     compilerErrorM $ "Expected single return in argument" ++ formatFullContextBrace c   let (Positional [t0],e) = head es'@@ -857,7 +927,7 @@     compilerErrorM $ "Expected 0 type parameters" ++ formatFullContextBrace c   when (length (pValues es) /= 1) $     compilerErrorM $ "Expected 1 argument" ++ formatFullContextBrace c-  es' <- sequence $ map compileExpression $ pValues es+  es' <- sequence $ map (compileExpression . snd) $ pValues es   when (length (pValues $ fst $ head es') /= 1) $     compilerErrorM $ "Expected single return in argument" ++ formatFullContextBrace c   let (Positional [t0],e) = head es'@@ -870,7 +940,7 @@     compilerErrorM $ "Expected 0 type parameters" ++ formatFullContextBrace c   when (length (pValues es) /= 1) $     compilerErrorM $ "Expected 1 argument" ++ formatFullContextBrace c-  es' <- sequence $ map compileExpression $ pValues es+  es' <- sequence $ map (compileExpression . snd) $ pValues es   when (length (pValues $ fst $ head es') /= 1) $     compilerErrorM $ "Expected single return in argument" ++ formatFullContextBrace c   let (Positional [t0],e) = head es'@@ -896,9 +966,15 @@             valueAsWrapped $ UnboxedPrimitive PrimString $ typeBase ++ "::TypeName(" ++ t' ++ ")") compileExpressionStart (BuiltinCall _ _) = undefined compileExpressionStart (ParensExpression _ e) = compileExpression e-compileExpressionStart (InlineAssignment c n e) = do+compileExpressionStart (InlineAssignment c n o e) = do   (VariableValue _ s t0 _) <- getWritableVariable c n-  (Positional [t],e') <- compileExpression e -- TODO: Get rid of the Positional matching here.+  e2 <- compileExpression e+  when (length (pValues $ fst $ e2) /= 1) $+    compilerErrorM $ "Expected single return" ++ formatFullContextBrace c+  let (Positional [t],e') = e2+  when (o == AssignIfEmpty && not (isOptionalValue t0)) $+    compilerErrorM $ "Variable must have an optional type" ++ formatFullContextBrace c+  when (o == AssignIfEmpty) $ csCheckVariableInit [UsedVariable c n]   r <- csResolver   fa <- csAllFilters   lift $ (checkValueAssignment r fa t t0) <??@@ -906,8 +982,19 @@   csUpdateAssigned n   scoped <- autoScope s   let lazy = s == CategoryScope-  return (Positional [t0],readStoredVariable lazy t0 $ "(" ++ scoped ++ variableName n ++-                                                     " = " ++ writeStoredVariable t0 e' ++ ")")+  let variable = scoped ++ variableName n+  let assign = variable ++ " = " ++ writeStoredVariable t0 e'+  let check = "BoxedValue::Present(" ++ useAsUnwrapped (readStoredVariable lazy t0 variable) ++ ")"+  let assignAndGet = readStoredVariable lazy t0 assign+  let alwaysAssign = if isWeakValue t0 && not (isWeakValue t)+                        then UnwrappedSingle $ "BoxedValue::Strong(" ++ useAsUnwrapped assignAndGet ++ ")"+                        else assignAndGet+  let maybeAssign = readStoredVariable lazy t0 $ check ++ " ? " ++ variable ++ " : (" ++ assign ++ ")"+  case o of+       AlwaysAssign -> return (Positional [t],alwaysAssign)+       AssignIfEmpty -> return (Positional [combineTypes t0 t],maybeAssign)+  where+    combineTypes (ValueType _ t1) (ValueType s _) = ValueType s t1 compileExpressionStart (InitializeValue c t es) = do   scope <- csCurrentScope   t' <- case scope of@@ -978,10 +1065,17 @@   -- written out as a literal looks like an unsigned overflow. Using ULL here   -- silences that warning.   return $ expressionFromLiteral PrimInt (show l ++ "ULL")-compileValueLiteral (DecimalLiteral _ l e) = do+compileValueLiteral (DecimalLiteral _ l e 10) = do   csAddRequired (Set.fromList [BuiltinFloat])   -- TODO: Check bounds.   return $ expressionFromLiteral PrimFloat (show l ++ "E" ++ show e)+compileValueLiteral (DecimalLiteral _ l e b) = do+  csAddRequired (Set.fromList [BuiltinFloat])+  let scale = if e < 0+                 then "/" ++ show (b^(-e))+                 else "*" ++ show (b^e)+  -- TODO: Check bounds.+  return $ expressionFromLiteral PrimFloat ("(" ++ show l ++ "E0" ++ scale ++ ")") compileValueLiteral (BoolLiteral _ True) = do   csAddRequired (Set.fromList [BuiltinBool])   return $ expressionFromLiteral PrimBool "true"@@ -999,12 +1093,12 @@  compileFunctionCall :: (Ord c, Show c, CollectErrorsM m,                         CompilerContext c m [String] a) =>-  Maybe String -> ScopedFunction c -> FunctionCall c ->+  Bool -> Maybe String -> ScopedFunction c -> FunctionCall c ->   CompilerState a m (ExpressionType,ExpressionValue)-compileFunctionCall e f (FunctionCall c _ ps es) = message ??> do+compileFunctionCall optionalValue e f (FunctionCall c _ ps es) = message ??> do   r <- csResolver   fa <- csAllFilters-  es' <- sequence $ map compileExpression $ pValues es+  es' <- sequence $ map (compileExpression . snd) $ pValues es   (ts,es'') <- lift $ getValues es'   f' <- lift $ parsedToFunctionType f   let psActual = case ps of@@ -1017,6 +1111,11 @@   lift $ mapCompilerM_ backgroundMessage $ zip3 (map vpParam $ pValues $ sfParams f) (pValues ps') (pValues ps2)   -- Called an extra time so arg count mismatches have reasonable errors.   lift $ processPairs_ (\_ _ -> return ()) (ftArgs f'') (Positional ts)+  lift $ if (length ts /= length (pValues es))+            then do+              mapCompilerM_ (labelNotAllowedError . fst) $ pValues es+              mapCompilerM_ (labelNotSetError . snd) $ pValues $ sfArgs f+            else processPairs_ checkArgLabel (fmap snd $ sfArgs f) (Positional $ zip ([0..] :: [Int]) $ map fst $ pValues es)   lift $ processPairs_ (checkArg r fa) (ftArgs f'') (Positional $ zip ([0..] :: [Int]) ts)   csAddRequired $ Set.unions $ map categoriesFromTypes $ pValues ps2   csAddRequired (Set.fromList [sfType f])@@ -1027,18 +1126,23 @@   call <- assemble e scoped scope (sfScope f) paramsArgs   return $ (ftReturns f'',OpaqueMulti call)   where+    labelNotAllowedError (Just l) = compilerErrorM $ "Arg label " ++ show l ++ " not allowed when forwarding multiple returns"+    labelNotAllowedError _ = return ()+    labelNotSetError (Just l) = compilerErrorM $ "Arg label " ++ show l ++ " cannot be set when forwarding multiple returns"+    labelNotSetError _ = return ()     replaceSelfParam self (AssignedInstance c2 t) = do       t' <- replaceSelfInstance self t       return $ AssignedInstance c2 t'     replaceSelfParam _ t = return t     message = "In call to " ++ show (sfName f) ++ " at " ++ formatFullContext c-    backgroundMessage (n,(InferredInstance c2),t) =-      compilerBackgroundM $ "Parameter " ++ show n ++ " (from " ++ show (sfType f) ++ "." ++-        show (sfName f) ++ ") inferred as " ++ show t ++ " at " ++ formatFullContext c2+    backgroundMessage (n,(InferredInstance c2),t) = do+      let funcName = functionDebugName (sfType f) f+      compilerBackgroundM $ "Parameter " ++ show n ++ " (from " ++ funcName +++        ") inferred as " ++ show t ++ " at " ++ formatFullContext c2     backgroundMessage _ = return ()     getParamsArgs ps2 paramEs argEs = do       psNames <- lift $ collectParamNames ps2-      asNames <- lift $ collectArgNames $ pValues es+      asNames <- lift $ collectArgNames $ map snd $ pValues es       canForward <- case (psNames,asNames) of                          (Just pn,Just an) -> csCanForward pn an                          _                 -> return False@@ -1054,11 +1158,14 @@     assemble Nothing scoped _ _ paramsArgs =       return $ scoped ++ callName (sfName f) ++ "(" ++ paramsArgs ++ ")"     assemble (Just e2) _ _ ValueScope paramsArgs =-      return $ valueBase ++ "::Call(" ++ e2 ++ ", " ++ functionName f ++ ", " ++ paramsArgs ++ ")"+      if optionalValue+         then return $ "TYPE_VALUE_CALL_UNLESS_EMPTY(" ++ e2 ++ ", " ++ functionName f ++ ", " ++ paramsArgs ++ ", " ++ show returnCount ++ ")"+         else return $ valueBase ++ "::Call(" ++ e2 ++ ", " ++ functionName f ++ ", " ++ paramsArgs ++ ")"     assemble (Just e2) _ _ TypeScope paramsArgs =       return $ typeBase ++ "::Call(" ++ e2 ++ ", " ++ functionName f ++ ", " ++ paramsArgs ++ ")"     assemble (Just e2) _ _ _ paramsArgs =       return $ e2 ++ ".Call(" ++ functionName f ++ ", " ++ paramsArgs ++ ")"+    returnCount = length $ pValues $ sfReturns f     -- TODO: Lots of duplication with assignments and initialization.     -- Single expression, but possibly multi-return.     getValues [(Positional ts,e2)] = return (ts,[useAsArgs e2])@@ -1072,6 +1179,16 @@       compilerErrorM $ "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)+    checkArgLabel (Just (CallArgLabel _ n1)) (_,Just (CallArgLabel _ n2))+      | n1 == n2 = return ()+    checkArgLabel l1 (i,l2) = "In argument " ++ show i ++ " to " ++ show (sfName f) ??> labelError l1 l2+    labelError (Just l1) (Just l2) =+      compilerErrorM $ "Expected arg label " ++ show l1 ++ " but got " ++ show l2+    labelError (Just l1) _ =+      compilerErrorM $ "Expected arg label " ++ show l1 ++ " but label is missing"+    labelError _ (Just l2) =+      compilerErrorM $ "Expected no arg label but got " ++ show l2+    labelError _ _ = return ()     collectParamNames = fmap sequence . mapCompilerM collectParamName     collectParamName = fmap getParamName . tryCompilerM . matchOnlyLeaf     getParamName (Just (JustParamName _ n)) = Just n@@ -1087,8 +1204,8 @@   Positional ValueType -> m (Positional GeneralInstance) guessParamsFromArgs r fa f ps ts = do   fm <- getFunctionFilterMap f-  args <- processPairs (\t1 t2 -> return $ TypePattern Covariant t1 t2) ts (fmap pvType $ sfArgs f)-  filts <- fmap concat $ processPairs (guessesFromFilters fm) ts (fmap pvType $ sfArgs f)+  args <- processPairs (\t1 t2 -> return $ TypePattern Covariant t1 t2) ts (fmap (pvType . fst) $ sfArgs f)+  filts <- fmap concat $ processPairs (guessesFromFilters fm) ts (fmap (pvType . fst) $ sfArgs f)   pa <- fmap Map.fromList $ processPairs toInstance (fmap vpParam $ sfParams f) ps   gs <- inferParamTypes r fa pa (args ++ filts)   gs' <- mergeInferredTypes r fa fm pa gs@@ -1096,7 +1213,10 @@   fmap Positional $ mapCompilerM (subPosition pa3) (pValues $ sfParams f) where     subPosition pa2 p =       case (vpParam p) `Map.lookup` pa2 of-           Just t  -> return t+           Just t  -> if not (hasInferredParams t)+                         then return t+                         else compilerErrorM $ "Could not infer param " +++                              show (vpParam p) ++ formatFullContextBrace (vpContext p)            Nothing -> compilerErrorM $ "Something went wrong inferring " ++                       show (vpParam p) ++ formatFullContextBrace (vpContext p)     toInstance p1 (AssignedInstance _ t) = return (p1,t)@@ -1122,17 +1242,39 @@ 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+  ctx <- getMainContext False tm em   runDataCompiler compiler ctx where     procedure = Procedure [] [IgnoreValues [] e]     compiler = do       ctx0 <- getCleanContext       compileProcedure ctx0 procedure >>= put +compileWrapTestcase :: (Ord c, Show c, CollectErrorsM m) =>+  CategoryMap c -> ([c],TypeInstance) -> m (CompiledData [String])+compileWrapTestcase tm (c,t) = do+  ctx <- getMainContext False tm Map.empty+  runDataCompiler compiler ctx <??+    "In custom testcase checker at " ++ formatFullContext c+  where+    compiler = do+      ctx0 <- getCleanContext+      lift (execStateT testcase ctx0) >>= put+    testcase = do+      let t2 = singleType $ JustTypeInstance t+      r <- csResolver+      lift $ validateGeneralInstanceForCall r Map.empty t2+      lift $ validateAssignment r Map.empty t2 [DefinesFilter (DefinesInstance BuiltinTestcase (Positional []))]+      start <- csGetTypeFunction c (Just t2) (FunctionName "start")+      finish <- csGetTypeFunction c (Just t2) (FunctionName "finish")+      csAddRequired $ Set.fromList [sfType start,sfType finish]+      csAddRequired $ categoriesFromTypes t2+      t2' <- expandGeneralInstance t2+      csWrite ["WrapTypeCall check_test(" ++ t2' ++ ", &" ++ functionName start ++ ", &" ++ functionName finish ++ ");"]+ compileTestProcedure :: (Ord c, Show c, CollectErrorsM m) =>   CategoryMap c -> ExprMap c -> TestProcedure c -> m (CompiledData [String]) compileTestProcedure tm em (TestProcedure c n cov p) = do-  ctx <- getMainContext tm em+  ctx <- getMainContext True tm em   p' <- runDataCompiler compiler ctx <??     "In unittest " ++ show n ++ formatFullContextBrace c   return $ mconcat [
src/Parser/Common.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -21,6 +21,7 @@ module Parser.Common (   ParseFromSource(..),   anyComment,+  assignEmptyOperator,   assignOperator,   blockComment,   builtinValues,@@ -43,6 +44,7 @@   kwDefer,   kwDefine,   kwDefines,+  kwDelegate,   kwElif,   kwElse,   kwEmpty,@@ -51,8 +53,9 @@   kwFalse,   kwIf,   kwIgnore,-  kwIn,   kwImmutable,+  kwIn,+  kwIdentify,   kwInterface,   kwOptional,   kwPresent,@@ -72,6 +75,7 @@   kwUnittest,   kwUpdate,   kwValue,+  kwVisibility,   kwWeak,   kwWhile,   labeled,@@ -92,7 +96,6 @@   parseDec,   parseHex,   parseOct,-  parseSubOne,   pragmaArgsEnd,   pragmaArgsStart,   pragmaEnd,@@ -110,8 +113,10 @@   statementStart,   stringChar,   string_,+  swapOperator,   typeSymbolGet,   valueSymbolGet,+  valueSymbolMaybeGet, ) where  import Data.Char@@ -145,6 +150,9 @@ valueSymbolGet :: TextParser () valueSymbolGet = sepAfter (string_ ".") +valueSymbolMaybeGet :: TextParser ()+valueSymbolMaybeGet = sepAfter (string_ "&.")+ categorySymbolGet :: TextParser () categorySymbolGet = labeled ":" $ useNewOperators <|> sepAfter (string_ ":") @@ -164,6 +172,12 @@ assignOperator :: TextParser () assignOperator = operator "<-" >> return () +assignEmptyOperator :: TextParser ()+assignEmptyOperator = operator "<-|" >> return ()++swapOperator :: TextParser ()+swapOperator = operator "<->" >> return ()+ infixFuncStart :: TextParser () infixFuncStart = sepAfter (string_ "`") @@ -209,6 +223,9 @@ kwDefines :: TextParser () kwDefines = keyword "defines" +kwDelegate :: TextParser ()+kwDelegate = keyword "delegate"+ kwElif :: TextParser () kwElif = keyword "elif" @@ -230,15 +247,18 @@ kwIf :: TextParser () kwIf = keyword "if" -kwIn :: TextParser ()-kwIn = keyword "in"- kwIgnore :: TextParser () kwIgnore = keyword "_"  kwImmutable :: TextParser () kwImmutable = keyword "immutable" +kwIn :: TextParser ()+kwIn = keyword "in"++kwIdentify :: TextParser ()+kwIdentify = keyword "identify"+ kwInterface :: TextParser () kwInterface = keyword "interface" @@ -296,6 +316,9 @@ kwValue :: TextParser () kwValue = keyword "@value" +kwVisibility :: TextParser ()+kwVisibility = keyword "visibility"+ kwWeak :: TextParser () kwWeak = keyword "weak" @@ -330,6 +353,7 @@     kwDefer,     kwDefine,     kwDefines,+    kwDelegate,     kwElif,     kwElse,     kwEmpty,@@ -337,9 +361,10 @@     kwFail,     kwFalse,     kwIf,-    kwIn,     kwIgnore,     kwImmutable,+    kwIn,+    kwIdentify,     kwInterface,     kwOptional,     kwPresent,@@ -359,6 +384,7 @@     kwUnittest,     kwUpdate,     kwValue,+    kwVisibility,     kwWeak,     kwWhile   ]@@ -433,7 +459,7 @@ operator :: String -> TextParser String operator o = labeled o $ do   string_ o-  notFollowedBy operatorSymbol+  try anyComment <|> notFollowedBy operatorSymbol   optionalSpace   return o @@ -481,20 +507,17 @@   | c >= 'a' && c <= 'f' = 10 + ord(c) - ord('a')   | otherwise = undefined -parseDec :: TextParser Integer-parseDec = labeled "base-10" $ fmap snd $ parseIntCommon 10 digitChar--parseHex :: TextParser Integer-parseHex = labeled "base-16" $ fmap snd $ parseIntCommon 16 hexDigitChar+parseDec :: TextParser (Integer,Integer)+parseDec = labeled "base-10" $ parseIntCommon 10 digitChar -parseOct :: TextParser Integer-parseOct = labeled "base-8" $ fmap snd $ parseIntCommon 8 octDigitChar+parseHex :: TextParser (Integer,Integer)+parseHex = labeled "base-16" $ parseIntCommon 16 hexDigitChar -parseBin :: TextParser Integer-parseBin = labeled "base-2" $ fmap snd $ parseIntCommon 2 (oneOf "01")+parseOct :: TextParser (Integer,Integer)+parseOct = labeled "base-8" $ parseIntCommon 8 octDigitChar -parseSubOne :: TextParser (Integer,Integer)-parseSubOne = parseIntCommon 10 digitChar+parseBin :: TextParser (Integer,Integer)+parseBin = labeled "base-2" $ parseIntCommon 2 (oneOf "01")  parseIntCommon :: Integer -> TextParser Char -> TextParser (Integer,Integer) parseIntCommon b p = do
src/Parser/IntegrationTest.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2020 Kevin P. Barry+Copyright 2020,2023 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.@@ -28,6 +28,7 @@ import Parser.Procedure () import Parser.TextParser import Parser.TypeCategory ()+import Parser.TypeInstance () import Types.IntegrationTest  @@ -56,20 +57,26 @@         c <- getSourceContext         keyword "error"         return $ ExpectCompilerError [c]-      resultCrash = labeled "crash expectation" $ do+      resultCrash = labeled "failure expectation" $ do         c <- getSourceContext-        keyword "crash"-        return $ ExpectRuntimeError [c]+        keyword "failure"+        t <- fmap Just parseTestcaseType <|> return Nothing+        return $ ExpectRuntimeError [c] t       resultSuccess = labeled "success expectation" $ do         c <- getSourceContext         keyword "success"-        return $ ExpectRuntimeSuccess [c]+        t <- fmap Just parseTestcaseType <|> return Nothing+        return $ ExpectRuntimeSuccess [c] t+      parseTestcaseType = do+        c <- getSourceContext+        t <- sourceParser+        return ([c],t)       parseArgs = labeled "testcase args" $ do         keyword "args"         many (sepAfter quotedString)       parseTimeout = labeled "testcase timeout" $ do         keyword "timeout"-        fmap Just (sepAfter parseDec)+        fmap (Just . snd) (sepAfter parseDec)       requireOrExclude = parseAny2 require exclude where         require = do           keyword "require"
src/Parser/Procedure.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -133,14 +133,32 @@                  parseFailCall <|>                  parseExitCall <|>                  parseVoid <|>+                 parseSwap <|>                  parseAssign <|>                  parsePragma <|>                  parseIgnore where     parseAssign = labeled "assignment" $ do       c <- getSourceContext       as <- sepBy sourceParser (sepAfter $ string_ ",")+      case as of+           [ExistingVariable (InputValue _ n)] -> parseAssignEmpty c n <|> parseAlwaysAssign c as+           _ -> parseAlwaysAssign c as+    parseAssignEmpty c n = do+      assignEmptyOperator+      e <- sourceParser+      statementEnd+      return $ AssignmentEmpty [c] n e+    parseAlwaysAssign c as = do       assignOperator       assignExpr c as <|> assignDefer c as+    parseSwap = labeled "swap" $ do+      c <- getSourceContext+      l <- try $ do+        var <- sourceParser+        swapOperator+        return var+      r <- sourceParser+      return $ VariableSwap [c] l r     assignExpr c as = do       e <- sourceParser       statementEnd@@ -411,7 +429,7 @@     asInfix [e] [] <|> return e     where       -- NOTE: InitializeValue is parsed as ExpressionStart.-      notInfix = literal <|> try unaryBuiltin <|> unary <|> expression+      notInfix = literal <|> try unaryBuiltin <|> unary <|> delegatedCall <|> expression       asInfix es os = do         c <- getSourceContext         o <- infixOperator <|> functionOperator@@ -443,16 +461,30 @@                             (sepBy sourceParser (sepAfter $ string_ ",")) <|> return []         infixFuncEnd         e <- notInfix-        return $ Expression [c] (BuiltinCall [c] $ FunctionCall [c] n (Positional ps) (Positional [e])) []+        return $ Expression [c] (BuiltinCall [c] $ FunctionCall [c] n (Positional ps) (Positional [(Nothing,e)])) []       unary = do         c <- getSourceContext         o <- unaryOperator <|> functionOperator         e <- notInfix         return $ UnaryExpression [c] o e+      delegatedCall = do+        kwDelegate+        sepAfter_ $ string "->"+        try delegateCall <|> delegateInit+      delegateInit = do+        c <- getSourceContext+        t <- (paramSelf >> return Nothing) <|> fmap Just sourceParser+        return $ DelegatedInitializeValue [c] t+      delegateCall = do+        c <- getSourceContext+        infixFuncStart+        f <- sourceParser+        infixFuncEnd+        return $ DelegatedFunctionCall [c] f       expression = labeled "expression" $ do         c <- getSourceContext         s <- sourceParser-        vs <- many sourceParser+        vs <- many (try sourceParser)         return $ Expression [c] s vs  instance ParseFromSource (FunctionQualifier SourceContext) where@@ -514,24 +546,30 @@                       (sepBy sourceParser (sepAfter $ string_ ",")) <|> return []   es <- between (sepAfter $ string_ "(")                 (sepAfter $ string_ ")")-                (sepBy sourceParser (sepAfter $ string_ ","))-  return $ FunctionCall [c] n (Positional ps) (Positional es)+                (sepBy parseArg (sepAfter $ string_ ","))+  return $ FunctionCall [c] n (Positional ps) (Positional es) where+    parseArg = do+      l <- try (fmap Just sourceParser) <|> return Nothing+      e <- sourceParser+      return (l,e)  builtinFunction :: TextParser FunctionName builtinFunction = foldr (<|>) empty $ map try [-    kwPresent >> return BuiltinPresent,-    kwReduce >> return BuiltinReduce,-    kwRequire >> return BuiltinRequire,-    kwStrong >> return BuiltinStrong,+    kwPresent  >> return BuiltinPresent,+    kwReduce   >> return BuiltinReduce,+    kwRequire  >> return BuiltinRequire,+    kwStrong   >> return BuiltinStrong,+    kwIdentify >> return BuiltinIdentify,     kwTypename >> return BuiltinTypename   ]  builtinUnary :: TextParser FunctionName builtinUnary = foldr (<|>) empty $ map try [-    kwPresent >> return BuiltinPresent,-    kwReduce >> return BuiltinReduce,-    kwRequire >> return BuiltinRequire,-    kwStrong >> return BuiltinStrong+    kwPresent  >> return BuiltinPresent,+    kwReduce   >> return BuiltinReduce,+    kwRequire  >> return BuiltinRequire,+    kwStrong   >> return BuiltinStrong,+    kwIdentify >> return BuiltinIdentify   ]  instance ParseFromSource (ExpressionStart SourceContext) where@@ -542,13 +580,15 @@                  builtinValue <|>                  sourceContext <|>                  exprLookup <|>+                 exprMacro <|>                  categoryCall <|>                  -- Keep this before typeCall, since it does a look-ahead for {.                  initalize <|>                  typeCall <|>                  stringLiteral <|>                  charLiteral <|>-                 boolLiteral where+                 boolLiteral <|>+                 emptyLiteral where     parens = do       c <- getSourceContext       sepAfter (string_ "(")@@ -558,9 +598,9 @@     assign :: SourceContext -> TextParser (ExpressionStart SourceContext)     assign c = do       n <- sourceParser-      assignOperator+      o <- (assignEmptyOperator >> return AssignIfEmpty) <|> (assignOperator >> return AlwaysAssign)       e <- sourceParser-      return $ InlineAssignment [c] n e+      return $ InlineAssignment [c] n o e     expr :: SourceContext -> TextParser (ExpressionStart SourceContext)     expr c = do       e <- sourceParser@@ -584,6 +624,9 @@       case pragma of            (PragmaExprLookup c name) -> return $ NamedMacro c name            _ -> undefined  -- Should be caught above.+    exprMacro = do+      (c,macro) <- macroExpression+      return $ ExpressionMacro [c] macro     variableOrUnqualified = do       c <- getSourceContext       n <- sourceParser :: TextParser VariableName@@ -634,61 +677,62 @@       c <- getSourceContext       b <- try $ (kwTrue >> return True) <|> (kwFalse >> return False)       return $ UnambiguousLiteral $ BoolLiteral [c] b+    emptyLiteral = do+      c <- getSourceContext+      kwEmpty+      return $ UnambiguousLiteral $ EmptyLiteral [c]  instance ParseFromSource (ValueLiteral SourceContext) where   sourceParser = labeled "literal" $-                 -- NOTE: StringLiteral, CharLiteral, and BoolLiteral are parsed-                 -- as ExpressionStart.-                 escapedInteger <|>-                 integerOrDecimal <|>-                 emptyLiteral where-    escapedInteger = do+                 -- NOTE: StringLiteral, CharLiteral, BoolLiteral , and+                 -- EmptyLiteral are parsed as ExpressionStart.+                 escapedIntegerOrDecimal <|>+                 integerOrDecimal where+    escapedIntegerOrDecimal = do       c <- getSourceContext       escapeStart       b <- oneOf "bBoOdDxX"-      d <- case b of-               'b' -> parseBin-               'B' -> parseBin-               'o' -> parseOct-               'O' -> parseOct-               'd' -> parseDec-               'D' -> parseDec-               'x' -> parseHex-               'X' -> parseHex-               _ -> undefined-      optionalSpace-      return $ IntegerLiteral [c] True d+      let (digitParser,base) = case b of+                                    'b' -> (parseBin,2)+                                    'B' -> (parseBin,2)+                                    'o' -> (parseOct,8)+                                    'O' -> (parseOct,8)+                                    'd' -> (parseDec,10)+                                    'D' -> (parseDec,10)+                                    'x' -> (parseHex,16)+                                    'X' -> (parseHex,16)+                                    _ -> undefined+      d <- fmap snd digitParser+      decimal c d False base digitParser <|> integer c d True     integerOrDecimal = do       c <- getSourceContext-      d <- parseDec-      decimal c d <|> integer c d-    decimal c d = do+      d <- fmap snd parseDec+      decimal c d True 10 parseDec <|> integer c d False+    decimal c d allowExp base digitParser = do       char_ '.'-      (n,d2) <- parseSubOne-      e <- decExponent <|> return 0+      (n,d2) <- digitParser+      e <- if allowExp+              then decExponent <|> return 0+              else return 0       optionalSpace-      return $ DecimalLiteral [c] (d*10^n + d2) (e - n)+      return $ DecimalLiteral [c] (d*base^n + d2) (e - n) base     decExponent = do       string_ "e" <|> string_ "E"       s <- (string_ "+" >> return 1) <|> (string_ "-" >> return (-1)) <|> return 1-      e <- parseDec+      e <- fmap snd parseDec       return (s*e)-    integer c d = do+    integer c d unsigned = do       optionalSpace-      return $ IntegerLiteral [c] False d-    emptyLiteral = do-      c <- getSourceContext-      kwEmpty-      return $ EmptyLiteral [c]+      return $ IntegerLiteral [c] unsigned d  instance ParseFromSource (ValueOperation SourceContext) where-  sourceParser = try valueCall <|> try conversion <|> selectReturn where+  sourceParser = valueCall <|> conversion <|> selectReturn where     valueCall = labeled "function call" $ do       c <- getSourceContext-      valueSymbolGet+      o <- (valueSymbolGet >> return AlwaysCall) <|> (valueSymbolMaybeGet >> return CallUnlessEmpty)       n <- sourceParser       f <- parseFunctionCall c n-      return $ ValueCall [c] f+      return $ ValueCall [c] o f     conversion = labeled "type conversion" $ do       c <- getSourceContext       inferredParam@@ -697,7 +741,7 @@     selectReturn = labeled "return selection" $ do       c <- getSourceContext       sepAfter_ (string_ "{")-      pos <- labeled "return position" parseDec+      pos <- labeled "return position" $ fmap snd parseDec       sepAfter_ (string_ "}")       return $ SelectReturn [c] (fromIntegral pos) @@ -735,6 +779,10 @@ pragmaSourceContext :: TextParser (PragmaExpr SourceContext) pragmaSourceContext = autoPragma "SourceContext" $ Left parseAt where   parseAt c = PragmaSourceContext c++macroExpression :: TextParser (SourceContext,MacroExpression)+macroExpression = callTrace where+  callTrace = autoPragma "CallTrace" $ Left (flip (,) MacroCallTrace)  data MarkType = ReadOnly | Hidden deriving (Show) 
src/Parser/TypeCategory.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019,2021 Kevin P. Barry+Copyright 2019,2021,2023 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.@@ -69,9 +69,9 @@       open       pg <- pragmas       (rs,ds,vs) <- parseRefinesDefinesFilters-      fs <- flip sepBy optionalSpace $ parseScopedFunction parseScope (return n)+      (fs,fv) <- parseFunctionsWithVisibility $ parseScopedFunction parseScope (return n)       close-      return $ ValueConcrete [c] NoNamespace n pg ps rs ds vs fs+      return $ ValueConcrete [c] NoNamespace n pg fv ps rs ds vs fs     pragmas = fmap (:[]) immutable <|> return []     immutable = do       c <- getSourceContext@@ -161,6 +161,43 @@     e <- sepAfter $ many alphaNumChar     return $ FunctionName (b:e) +instance ParseFromSource (CallArgLabel SourceContext) where+  sourceParser = labeled "arg label" $ do+    c <- getSourceContext+    b <- lowerChar+    e <- many alphaNumChar+    sepAfter $ char_ ':'+    return $ CallArgLabel [c] (b:e ++ ":")++instance ParseFromSource (FunctionVisibility SourceContext) where+  sourceParser = labeled "visibility" $ do+    c <- getSourceContext+    kwVisibility+    visDefault <|> visTypes c where+      visDefault = do+        kwIgnore+        return $ FunctionVisibilityDefault+      visTypes c = do+        ts <- sepBy1 singleType (sepAfter $ string ",")+        return $ FunctionVisibility [c] ts+      singleType = do+        c <- getSourceContext+        t <- sourceParser+        return ([c],t)++parseFunctionsWithVisibility :: TextParser (ScopedFunction SourceContext) ->+  TextParser ([ScopedFunction SourceContext],[FunctionVisibility SourceContext])+parseFunctionsWithVisibility func = labeled "visibility" $ sepBy anyType optionalSpace >>= merge FunctionVisibilityDefault where+  anyType = fmap Left func <|> fmap Right sourceParser+  merge v0 (Left f:ps) = do+    (fs,vs) <- merge v0 ps+    return (setVis v0 f:fs,vs)+  merge _ (Right v:ps) = do+    (fs,vs) <- merge v ps+    return (fs,v:vs)+  merge _ _ = return ([],[])+  setVis v (ScopedFunction c n t s _ as rs ps fs ms) = (ScopedFunction c n t s v as rs ps fs ms)+ parseScopedFunction ::   TextParser SymbolScope -> TextParser CategoryName -> TextParser (ScopedFunction SourceContext) parseScopedFunction sp tp = labeled "function" $ do@@ -168,10 +205,10 @@   (s,t,n) <- try parseName   ps <- fmap Positional $ noParams <|> someParams   fa <- parseFilters-  as <- fmap Positional $ typeList "argument type"+  as <- fmap Positional $ typeList "arg label" singleArg   sepAfter_ (string "->")-  rs <- fmap Positional $ typeList "return type"-  return $ ScopedFunction [c] n t s as rs ps fa []+  rs <- fmap Positional $ typeList "return type" singleReturn+  return $ ScopedFunction [c] n t s FunctionVisibilityDefault as rs ps fa []   where     parseName = do       s <- sp -- Could be a constant, i.e., nothing consumed.@@ -187,10 +224,16 @@       c <- getSourceContext       n <- sourceParser       return $ ValueParam [c] n Invariant-    typeList l = between (sepAfter $ string_ "(")-                         (sepAfter $ string_ ")")-                         (sepBy (labeled l $ singleType) (sepAfter $ string ","))-    singleType = do+    typeList l parseVal = between (sepAfter $ string_ "(")+                                  (sepAfter $ string_ ")")+                                  (sepBy (labeled l $ parseVal) (sepAfter $ string ","))+    singleArg = do+      c <- getSourceContext+      t <- sourceParser+      optionalSpace+      n <- fmap Just sourceParser <|> return Nothing+      return $ (PassedValue [c] t,n)+    singleReturn = do       c <- getSourceContext       t <- sourceParser       return $ PassedValue [c] t
src/Parser/TypeInstance.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2020,2022 Kevin P. Barry+Copyright 2019-2020,2022-2023 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.@@ -82,7 +82,10 @@         | n == "Float"      = BuiltinFloat         | n == "String"     = BuiltinString         | n == "Pointer"    = BuiltinPointer+        | n == "Identifier" = BuiltinIdentifier         | n == "Formatted"  = BuiltinFormatted+        | n == "Order"      = BuiltinOrder+        | n == "Testcase"   = BuiltinTestcase         | otherwise = CategoryName n  instance ParseFromSource ParamName where
src/Test/ParseMetadata.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2020-2021 Kevin P. Barry+Copyright 2020-2021,2023 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.@@ -427,12 +427,12 @@                   [(MacroName "MY_MACRO",                     Expression _ (BuiltinCall _                       (FunctionCall _ BuiltinRequire (Positional [])-                        (Positional [Literal (EmptyLiteral _)]))) []),+                        (Positional [(Nothing,Expression _ (UnambiguousLiteral (EmptyLiteral _)) [])]))) []),                    (MacroName "MY_OTHER_MACRO",                     Expression _                       (TypeCall _ _                         (FunctionCall _ (FunctionName "execute") (Positional [])-                        (Positional [Expression _ (UnambiguousLiteral (StringLiteral _ "this is a string\n")) []]))) [])+                        (Positional [(Nothing,Expression _ (UnambiguousLiteral (StringLiteral _ "this is a string\n")) [])]))) [])                     ] -> True                   _ -> False), 
src/Test/Procedure.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -83,8 +83,11 @@     checkShortParseSuccess "\\ (false).call()",     checkShortParseSuccess "\\ false.call()",     checkShortParseFail "\\ 1.call()",-    checkShortParseFail "\\ empty.call()",+    checkShortParseSuccess "\\ empty.call()", +    checkShortParseSuccess "\\ foo(arg1: 123)",+    checkShortParseFail "\\ foo(arg1 : 123)",+     checkShortParseSuccess "x <- var.func()",     checkShortParseFail "x <- var.func() var.func()",     checkShortParseFail "x <- y <- var.func()",@@ -113,6 +116,19 @@     checkShortParseSuccess "_, weak T<#x> x <- var.func()",     checkShortParseFail "_, weak T<#x> x <- T<#x> x", +    checkShortParseSuccess "a <-> b",+    checkShortParseFail "self <-> b",+    checkShortParseFail "a <-> self",+    checkShortParseFail "_ <-> b",+    checkShortParseFail "a <-> _",+    checkShortParseFail "\\ a <-> b",+    checkShortParseFail "a, b <-> c",+    checkShortParseFail "a <-> b, c",+    checkShortParseFail "#a <-> b",+    checkShortParseFail "a <-> #b",+    checkShortParseFail "a.foo() <-> b",+    checkShortParseFail "a <-> b.foo()",+     checkShortParseSuccess "if (var.func()) { \\ val.call() }",     checkShortParseSuccess "if (present(var)) { \\ val.call() }",     checkShortParseFail "if (T<#x> x) { \\ val.call() }",@@ -190,6 +206,15 @@     checkShortParseSuccess "\\ ~x | ~y",     checkShortParseSuccess "\\ ~x ^ ~y", +    checkShortParseSuccess "\\ a+b",+    checkShortParseFail "\\ a++b",+    checkShortParseFail "\\ a+/b",+    checkShortParseFail "\\ a/=b",+    checkShortParseSuccess "\\ a+/*c*//*c*/d",+    checkShortParseSuccess "\\ a+//c\nd",+    checkShortParseSuccess "\\ a/*c*//*c*/+d",+    checkShortParseSuccess "\\ a//c\n+d",+     checkShortParseSuccess "x <- y + z",     checkShortParseSuccess "x <- !y == !z",     checkShortParseSuccess "x <- (x + y) / z",@@ -207,7 +232,6 @@     checkShortParseSuccess "x <- \\x123aBc + \\x123aBc",     checkShortParseFail "x <- \\x123aQc",     checkShortParseFail "x <- \\x",-    checkShortParseFail "x <- \\x1.2",     checkShortParseSuccess "x <- \" return \\\"\\\" \" + \"1fds\"",     checkShortParseFail "x <- \"fsdfd",     checkShortParseFail "x <- \"\"fsdfd",@@ -242,6 +266,28 @@     checkShortParseSuccess "x <- `reduce<#x,#y>` y",     checkShortParseFail "x <- `typename<#y>` y", +    checkShortParseSuccess "x <- 123.456",+    checkShortParseSuccess "x <- \\d123.456",+    checkShortParseFail "x <- 123.",+    checkShortParseFail "x <- \\d123.",+    checkShortParseSuccess "x <- 123.456E1",+    checkShortParseFail "x <- \\d123.456E1",++    checkShortParseSuccess "x <- \\b101.101",+    checkShortParseFail "x <- \\b101.",+    checkShortParseFail "x <- \\b101.101E1",++    checkShortParseSuccess "x <- \\xABC.DEF",+    checkShortParseFail "x <- \\xABC.",++    checkShortParseSuccess "x <- \\o123.456",+    checkShortParseFail "x <- \\o123.",+    checkShortParseFail "x <- \\o123.456E1",++    checkShortParseFail "Int x <-| 123",+    checkShortParseFail "_ <-| 123",+    checkShortParseFail "x, y <-| 123",+     checkParsesAs "'\"'"                   (\e -> case e of                               (Expression _ (UnambiguousLiteral (CharLiteral _ '"')) []) -> True@@ -322,7 +368,7 @@                                     (FunctionSpec _                                       (ValueFunction _                                         (Expression _ (BuiltinCall _ (FunctionCall _ BuiltinRequire (Positional [])-                                          (Positional [Expression _ (NamedVariable (OutputValue _ (VariableName "x"))) []]))) []))+                                          (Positional [(Nothing,Expression _ (NamedVariable (OutputValue _ (VariableName "x"))) [])]))) []))                                         (FunctionName "foo") (Positional [])))                                 (Literal (IntegerLiteral _ False 2)) -> True                               _ -> False),@@ -374,7 +420,7 @@                                     (FunctionSpec _                                       (ValueFunction _                                         (Expression _ (BuiltinCall _ (FunctionCall _ BuiltinRequire (Positional [])-                                          (Positional [Expression _ (NamedVariable (OutputValue _ (VariableName "x"))) []]))) []))+                                          (Positional [(Nothing,Expression _ (NamedVariable (OutputValue _ (VariableName "x"))) [])]))) []))                                         (FunctionName "not") (Positional [])))                                 (Literal (IntegerLiteral _ False 2)) -> True                               _ -> False),@@ -424,15 +470,27 @@                                    _ -> False),      checkParsesAs "1.2345" (\e -> case e of-                                       (Literal (DecimalLiteral _ 12345 (-4))) -> True+                                       (Literal (DecimalLiteral _ 12345 (-4) 10)) -> True                                        _ -> False),      checkParsesAs "1.2345E+4" (\e -> case e of-                                          (Literal (DecimalLiteral _ 12345 0)) -> True+                                          (Literal (DecimalLiteral _ 12345 0 10)) -> True                                           _ -> False),      checkParsesAs "1.2345E-4" (\e -> case e of-                                          (Literal (DecimalLiteral _ 12345 (-8))) -> True+                                          (Literal (DecimalLiteral _ 12345 (-8) 10)) -> True+                                          _ -> False),++    checkParsesAs "\\xF.F" (\e -> case e of+                                          (Literal (DecimalLiteral _ 255 (-1) 16)) -> True+                                          _ -> False),++    checkParsesAs "\\o7.7" (\e -> case e of+                                          (Literal (DecimalLiteral _ 63 (-1) 8)) -> True+                                          _ -> False),++    checkParsesAs "\\b1.1" (\e -> case e of+                                          (Literal (DecimalLiteral _ 3 (-1) 2)) -> True                                           _ -> False),      checkParseMatch "$NoTrace$" pragmaNoTrace
src/Test/TypeCategory.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -20,8 +20,9 @@ module Test.TypeCategory (tests) where  import Control.Arrow-import Control.Monad ((>=>))+import Control.Monad ((>=>),when) import System.FilePath+import Text.Regex.TDFA import qualified Data.Map as Map import qualified Data.Set as Set @@ -32,7 +33,6 @@ import Parser.TextParser (SourceContext) import Parser.TypeCategory () import Test.Common-import Types.Builtin import Types.TypeCategory import Types.TypeInstance import Types.Variance@@ -84,67 +84,73 @@     checkShortParseFail "concrete Type<#x> { #x defines #self }",     checkShortParseFail "@value interface Type { call<#self> () -> () }", -    checkOperationSuccess ("testfiles" </> "value_refines_value.0rx") (checkConnectedTypes defaultCategories),-    checkOperationFail ("testfiles" </> "value_refines_instance.0rx") (checkConnectedTypes defaultCategories),-    checkOperationFail ("testfiles" </> "value_refines_concrete.0rx") (checkConnectedTypes defaultCategories),+    checkOperationSuccess ("testfiles" </> "value_refines_value.0rx") (checkConnectedTypes emptyCategoryMap),+    checkOperationFail ("testfiles" </> "value_refines_instance.0rx") (checkConnectedTypes emptyCategoryMap),+    checkOperationFail ("testfiles" </> "value_refines_concrete.0rx") (checkConnectedTypes emptyCategoryMap), -    checkOperationSuccess ("testfiles" </> "concrete_refines_value.0rx") (checkConnectedTypes defaultCategories),-    checkOperationFail ("testfiles" </> "concrete_refines_instance.0rx") (checkConnectedTypes defaultCategories),-    checkOperationFail ("testfiles" </> "concrete_refines_concrete.0rx") (checkConnectedTypes defaultCategories),-    checkOperationSuccess ("testfiles" </> "concrete_defines_instance.0rx") (checkConnectedTypes defaultCategories),-    checkOperationFail ("testfiles" </> "concrete_defines_value.0rx") (checkConnectedTypes defaultCategories),-    checkOperationFail ("testfiles" </> "concrete_defines_concrete.0rx") (checkConnectedTypes defaultCategories),+    checkOperationSuccess ("testfiles" </> "concrete_refines_value.0rx") (checkConnectedTypes emptyCategoryMap),+    checkOperationFail ("testfiles" </> "concrete_refines_instance.0rx") (checkConnectedTypes emptyCategoryMap),+    checkOperationFail ("testfiles" </> "concrete_refines_concrete.0rx") (checkConnectedTypes emptyCategoryMap),+    checkOperationSuccess ("testfiles" </> "concrete_defines_instance.0rx") (checkConnectedTypes emptyCategoryMap),+    checkOperationFail ("testfiles" </> "concrete_defines_value.0rx") (checkConnectedTypes emptyCategoryMap),+    checkOperationFail ("testfiles" </> "concrete_defines_concrete.0rx") (checkConnectedTypes emptyCategoryMap),      checkOperationSuccess       ("testfiles" </> "concrete_refines_value.0rx")-      (checkConnectedTypes $ Map.fromList [+      (checkConnectedTypes $ toCategoryMap [           (CategoryName "Parent2",InstanceInterface [] NoNamespace (CategoryName "Parent2") [] [] [])         ]),     checkOperationFail       ("testfiles" </> "concrete_refines_value.0rx")-      (checkConnectedTypes $ Map.fromList [+      (checkConnectedTypes $ toCategoryMap [           (CategoryName "Parent",InstanceInterface [] NoNamespace (CategoryName "Parent") [] [] [])         ]),      checkOperationSuccess       ("testfiles" </> "partial.0rx")-      (checkConnectedTypes $ Map.fromList [+      (checkConnectedTypes $ toCategoryMap [           (CategoryName "Parent",ValueInterface [] NoNamespace (CategoryName "Parent") [] [] [] [])         ]),     checkOperationFail       ("testfiles" </> "partial.0rx")-      (checkConnectedTypes $ Map.fromList [+      (checkConnectedTypes $ toCategoryMap [           (CategoryName "Parent",InstanceInterface [] NoNamespace (CategoryName "Parent") [] [] [])         ]),     checkOperationFail       ("testfiles" </> "partial.0rx")-      (checkConnectedTypes $ Map.fromList [-          (CategoryName "Parent",ValueConcrete [] NoNamespace (CategoryName "Parent") [] [] [] [] [] [])+      (checkConnectedTypes $ toCategoryMap [+          (CategoryName "Parent",ValueConcrete [] NoNamespace (CategoryName "Parent") [] [] [] [] [] [] [])         ]),+    checkOperationFailWith "Parent.+not found"+      ("testfiles" </> "partial.0rx")+      (checkConnectedTypes emptyCategoryMap),+    checkOperationFailWith "Parent.+not visible"+      ("testfiles" </> "partial.0rx")+      (checkConnectedTypes $ CategoryMap (Map.fromList [(CategoryName "Parent",[])]) Map.empty), -    checkOperationSuccess ("testfiles" </> "value_refines_value.0rx") (checkConnectionCycles Map.empty),-    checkOperationSuccess ("testfiles" </> "concrete_refines_value.0rx") (checkConnectionCycles Map.empty),-    checkOperationSuccess ("testfiles" </> "concrete_defines_instance.0rx") (checkConnectionCycles Map.empty),-    checkOperationFail ("testfiles" </> "value_cycle.0rx") (checkConnectionCycles Map.empty),+    checkOperationSuccess ("testfiles" </> "value_refines_value.0rx") (checkConnectionCycles emptyCategoryMap),+    checkOperationSuccess ("testfiles" </> "concrete_refines_value.0rx") (checkConnectionCycles emptyCategoryMap),+    checkOperationSuccess ("testfiles" </> "concrete_defines_instance.0rx") (checkConnectionCycles emptyCategoryMap),+    checkOperationFail ("testfiles" </> "value_cycle.0rx") (checkConnectionCycles emptyCategoryMap),      checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts+        ts2 <- topoSortCategories emptyCategoryMap ts         map (show . getCategoryName) ts2 `containsPaired` [             "Object2","Object3","Object1","Type","Parent","Child"           ]),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2),      checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2         scrapeAllRefines ts3 `containsExactly` [             ("Object1","Object3<#y>"),             ("Object1","Object2"),@@ -164,7 +170,7 @@     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        existing  <- return $ Map.fromList [+        existing  <- return $ toCategoryMap [             (CategoryName "Parent2",InstanceInterface [] NoNamespace (CategoryName "Parent2") [] [] [])           ]         ts2 <- topoSortCategories existing ts@@ -172,7 +178,7 @@     checkOperationFail       ("testfiles" </> "flatten.0rx")       (\ts -> do-        existing  <- return $ Map.fromList [+        existing  <- return $ toCategoryMap [             (CategoryName "Parent",InstanceInterface [] NoNamespace (CategoryName "Parent") [] [] [])           ]         topoSortCategories existing ts),@@ -180,7 +186,7 @@     checkOperationSuccess       ("testfiles" </> "partial.0rx")       (\ts -> do-        existing  <- return $ Map.fromList [+        existing  <- return $ toCategoryMap [             (CategoryName "Parent",             ValueInterface [] NoNamespace (CategoryName "Parent") [] []                            [ValueRefine [] $ TypeInstance (CategoryName "Object1") (Positional []),@@ -198,33 +204,33 @@             ("Child","Object2")           ]), -    checkOperationSuccess ("testfiles" </> "valid_variances.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "contravariant_refines_covariant.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "contravariant_refines_invariant.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "covariant_refines_contravariant.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "covariant_refines_invariant.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "contravariant_defines_covariant.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "contravariant_defines_invariant.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "covariant_defines_contravariant.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "covariant_defines_invariant.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "concrete_duplicate_param.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "type_duplicate_param.0rx") (checkParamVariances defaultCategories),-    checkOperationFail ("testfiles" </> "value_duplicate_param.0rx") (checkParamVariances defaultCategories),+    checkOperationSuccess ("testfiles" </> "valid_variances.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "contravariant_refines_covariant.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "contravariant_refines_invariant.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "covariant_refines_contravariant.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "covariant_refines_invariant.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "contravariant_defines_covariant.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "contravariant_defines_invariant.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "covariant_defines_contravariant.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "covariant_defines_invariant.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "concrete_duplicate_param.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "type_duplicate_param.0rx") (checkParamVariances emptyCategoryMap),+    checkOperationFail ("testfiles" </> "value_duplicate_param.0rx") (checkParamVariances emptyCategoryMap),      checkOperationSuccess       ("testfiles" </> "concrete_refines_value.0rx")-      (checkParamVariances $ Map.fromList [+      (checkParamVariances $ toCategoryMap [           (CategoryName "Parent2",InstanceInterface [] NoNamespace (CategoryName "Parent2") [] [] [])         ]),     checkOperationFail       ("testfiles" </> "concrete_refines_value.0rx")-      (checkParamVariances $ Map.fromList [+      (checkParamVariances $ toCategoryMap [           (CategoryName "Parent",InstanceInterface [] NoNamespace (CategoryName "Parent") [] [] [])         ]),      checkOperationSuccess       ("testfiles" </> "partial_params.0rx")-      (checkParamVariances $ Map.fromList [+      (checkParamVariances $ toCategoryMap [           (CategoryName "Parent",            ValueInterface [] NoNamespace (CategoryName "Parent") []                           [ValueParam [] (ParamName "#w") Contravariant,@@ -232,7 +238,7 @@       ]),     checkOperationFail       ("testfiles" </> "partial_params.0rx")-      (checkParamVariances $ Map.fromList [+      (checkParamVariances $ toCategoryMap [           (CategoryName "Parent",            ValueInterface [] NoNamespace (CategoryName "Parent") []                           [ValueParam [] (ParamName "#w") Invariant,@@ -240,7 +246,7 @@       ]),     checkOperationFail       ("testfiles" </> "partial_params.0rx")-      (checkParamVariances $ Map.fromList [+      (checkParamVariances $ toCategoryMap [           (CategoryName "Parent",            ValueInterface [] NoNamespace (CategoryName "Parent") []                           [ValueParam [] (ParamName "#w") Contravariant,@@ -256,55 +262,55 @@     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2         rs <- getTypeRefines ts3 "Object1<#a,#b>" "Object1"         rs `containsPaired` ["#a","#b"]),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2         rs <- getTypeRefines ts3 "Object1<#a,#b>" "Object3"         rs `containsPaired` ["#b"]),     checkOperationFail       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2         rs <- getTypeRefines ts3 "Undefined<#a,#b>" "Undefined"         rs `containsPaired` ["#a","#b"]),     checkOperationFail       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2         rs <- getTypeRefines ts3 "Object1<#a>" "Object1"         rs `containsPaired` ["#a"]),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2         rs <- getTypeRefines ts3 "Parent<#t>" "Object1"         rs `containsPaired` ["#t","Object3<Object2>"]),     checkOperationFail       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2         getTypeRefines ts3 "Parent<#t>" "Child"),     checkOperationFail       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2         getTypeRefines ts3 "Child" "Type"),     checkOperationFail       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2         getTypeRefines ts3 "Child" "Missing"),      checkOperationSuccess@@ -362,64 +368,64 @@     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ta <- flattenAllConnections defaultCategories ts2 >>= declareAllTypes defaultCategories+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r [] "Child"),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ta <- flattenAllConnections defaultCategories ts2 >>= declareAllTypes defaultCategories+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r [] "[Child|Child]"),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ta <- flattenAllConnections defaultCategories ts2 >>= declareAllTypes defaultCategories+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r [] "[Child&Child]"),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ta <- flattenAllConnections defaultCategories ts2 >>= declareAllTypes defaultCategories+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r [] "Object2"),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ta <- flattenAllConnections defaultCategories ts2 >>= declareAllTypes defaultCategories+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r [] "[Object2|Object2]"),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ta <- flattenAllConnections defaultCategories ts2 >>= declareAllTypes defaultCategories+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r [] "[Object2&Object2]"),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ta <- flattenAllConnections defaultCategories ts2 >>= declareAllTypes defaultCategories+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeFail r [] "Type<Child>"),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ta <- flattenAllConnections defaultCategories ts2 >>= declareAllTypes defaultCategories+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeFail r [] "[Type<Child>|Type<Child>]"),     checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ta <- flattenAllConnections defaultCategories ts2 >>= declareAllTypes defaultCategories+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeFail r [] "[Type<Child>&Type<Child>]"), @@ -427,29 +433,29 @@     checkOperationSuccess       ("testfiles" </> "filters.0rx")       (\ts -> do-        ts2 <- topoSortCategories Map.empty ts-        ta <- flattenAllConnections Map.empty ts2 >>= declareAllTypes Map.empty+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r [] "Value0<Value1,Value2>"),     checkOperationSuccess       ("testfiles" </> "filters.0rx")       (\ts -> do-        ts2 <- topoSortCategories Map.empty ts-        ta <- flattenAllConnections Map.empty ts2 >>= declareAllTypes Map.empty+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r [] "Value0<Value1,Value1>"),     checkOperationSuccess       ("testfiles" </> "filters.0rx")       (\ts -> do-        ts2 <- topoSortCategories Map.empty ts-        ta <- flattenAllConnections Map.empty ts2 >>= declareAllTypes Map.empty+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r [] "Value0<Value3,Value2>"),     checkOperationSuccess       ("testfiles" </> "filters.0rx")       (\ts -> do-        ts2 <- topoSortCategories Map.empty ts-        ta <- flattenAllConnections Map.empty ts2 >>= declareAllTypes Map.empty+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r           ["#x","#y"]@@ -457,8 +463,8 @@     checkOperationSuccess       ("testfiles" </> "filters.0rx")       (\ts -> do-        ts2 <- topoSortCategories Map.empty ts-        ta <- flattenAllConnections Map.empty ts2 >>= declareAllTypes Map.empty+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r           ["#x","#y"]@@ -466,8 +472,8 @@     checkOperationSuccess       ("testfiles" </> "filters.0rx")       (\ts -> do-        ts2 <- topoSortCategories Map.empty ts-        ta <- flattenAllConnections Map.empty ts2 >>= declareAllTypes Map.empty+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r           ["#x","#y"]@@ -475,8 +481,8 @@     checkOperationSuccess       ("testfiles" </> "filters.0rx")       (\ts -> do-        ts2 <- topoSortCategories Map.empty ts-        ta <- flattenAllConnections Map.empty ts2 >>= declareAllTypes Map.empty+        ts2 <- topoSortCategories emptyCategoryMap ts+        ta <- flattenAllConnections emptyCategoryMap ts2 >>= declareAllTypes emptyCategoryMap         let r = CategoryResolver ta         checkTypeSuccess r           ["#x","#y"]@@ -485,222 +491,222 @@     checkOperationSuccess       ("testfiles" </> "requires_concrete.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2-        checkCategoryInstances defaultCategories ts3),+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2+        checkCategoryInstances emptyCategoryMap ts3),      -- TODO: Clean these tests up.     checkOperationSuccess       ("testfiles" </> "merged.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        ts3 <- flattenAllConnections defaultCategories ts2-        tm <- declareAllTypes defaultCategories ts3-        rs <- getRefines tm "Test"+        ts2 <- topoSortCategories emptyCategoryMap ts+        ts3 <- flattenAllConnections emptyCategoryMap ts2+        tm <- declareAllTypes emptyCategoryMap ts3+        rs <- getRefines (cmAvailable tm) "Test"         rs `containsExactly` ["Value0","Value1","Value2","Value3",                               "Value4<Value1,Value1>","Inherit1","Inherit2"]),      checkOperationSuccess       ("testfiles" </> "merged.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationSuccess       ("testfiles" </> "duplicate_refine.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationSuccess       ("testfiles" </> "duplicate_define.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationFail       ("testfiles" </> "refine_wrong_direction.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationFail       ("testfiles" </> "inherit_incompatible.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationSuccess       ("testfiles" </> "merge_incompatible.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),      checkOperationSuccess       ("testfiles" </> "flatten.0rx")       (\ts -> do-        let tm0 = Map.fromList [+        let tm0 = toCategoryMap [                     (CategoryName "Parent2",InstanceInterface [] NoNamespace (CategoryName "Parent2") [] [] [])                   ]         tm <- includeNewTypes tm0 ts-        rs <- getRefines tm "Child"+        rs <- getRefines (cmAvailable tm) "Child"         rs `containsExactly` ["Parent<Child>","Object2",                               "Object1<Child,Object3<Object2>>",                               "Object3<Object3<Object2>>"]),      checkOperationSuccess       ("testfiles" </> "category_function_param_match.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "function_param_clash.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "function_duplicate_param.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "function_bad_filter_param.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "function_bad_allows_variance.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "function_bad_requires_variance.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "function_bad_defines_variance.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "weak_arg.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "weak_return.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),      checkOperationSuccess       ("testfiles" </> "function_filters_satisfied.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationSuccess       ("testfiles" </> "function_requires_missed.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationSuccess       ("testfiles" </> "function_allows_missed.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationSuccess       ("testfiles" </> "function_defines_missed.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),      checkOperationSuccess       ("testfiles" </> "valid_function_variance.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "bad_value_arg_variance.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "bad_value_return_variance.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "bad_type_arg_variance.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),     checkOperationFail       ("testfiles" </> "bad_type_return_variance.0rx")-      (\ts -> checkCategoryInstances defaultCategories ts),+      (\ts -> checkCategoryInstances emptyCategoryMap ts),      checkOperationSuccess       ("testfiles" </> "valid_filter_variance.0rx")-      (\ts -> checkParamVariances defaultCategories ts),+      (\ts -> checkParamVariances emptyCategoryMap ts),     checkOperationSuccess       ("testfiles" </> "allows_variance_right.0rx")-      (\ts -> checkParamVariances defaultCategories ts),+      (\ts -> checkParamVariances emptyCategoryMap ts),     checkOperationSuccess       ("testfiles" </> "defines_variance_right.0rx")-      (\ts -> checkParamVariances defaultCategories ts),+      (\ts -> checkParamVariances emptyCategoryMap ts),     checkOperationSuccess       ("testfiles" </> "requires_variance_right.0rx")-      (\ts -> checkParamVariances defaultCategories ts),+      (\ts -> checkParamVariances emptyCategoryMap ts),     checkOperationSuccess       ("testfiles" </> "allows_variance_left.0rx")-      (\ts -> checkParamVariances defaultCategories ts),+      (\ts -> checkParamVariances emptyCategoryMap ts),     checkOperationSuccess       ("testfiles" </> "defines_variance_left.0rx")-      (\ts -> checkParamVariances defaultCategories ts),+      (\ts -> checkParamVariances emptyCategoryMap ts),     checkOperationSuccess       ("testfiles" </> "requires_variance_left.0rx")-      (\ts -> checkParamVariances defaultCategories ts),+      (\ts -> checkParamVariances emptyCategoryMap ts),      checkOperationFail       ("testfiles" </> "conflicting_declaration.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationFail       ("testfiles" </> "conflicting_inherited.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationSuccess       ("testfiles" </> "successful_merge.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationSuccess       ("testfiles" </> "merge_with_refine.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationFail       ("testfiles" </> "failed_merge.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationFail       ("testfiles" </> "ambiguous_merge_inherit.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationFail       ("testfiles" </> "merge_different_scopes.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),      checkOperationSuccess       ("testfiles" </> "successful_merge_params.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationFail       ("testfiles" </> "failed_merge_params.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationSuccess       ("testfiles" </> "preserve_merged.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationFail       ("testfiles" </> "conflict_in_preserved.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),     checkOperationSuccess       ("testfiles" </> "resolved_in_preserved.0rx")       (\ts -> do-        ts2 <- topoSortCategories defaultCategories ts-        flattenAllConnections defaultCategories ts2 >> return ()),+        ts2 <- topoSortCategories emptyCategoryMap ts+        flattenAllConnections emptyCategoryMap ts2 >> return ()),      checkOperationSuccess       ("testfiles" </> "valid_self.0rx")-      (includeNewTypes defaultCategories >=> const (return ())),+      (includeNewTypes emptyCategoryMap >=> const (return ())),     checkOperationFail       ("testfiles" </> "bad_merge_self.0rx")-      (includeNewTypes defaultCategories >=> const (return ())),+      (includeNewTypes emptyCategoryMap >=> const (return ())),     checkOperationFail       ("testfiles" </> "contravariant_self.0rx")-      (includeNewTypes defaultCategories >=> const (return ())),+      (includeNewTypes emptyCategoryMap >=> const (return ())),     checkOperationFail       ("testfiles" </> "invariant_self.0rx")-      (includeNewTypes defaultCategories >=> const (return ())),+      (includeNewTypes emptyCategoryMap >=> const (return ())),      checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Type1","#x")]@@ -708,7 +714,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Type2","#x"),("Type1","#x")]@@ -716,7 +722,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           []@@ -725,7 +731,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface1<Type2>","#x"),("Interface1<Type1>","#x")]@@ -734,7 +740,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface2<Type2>","#x"),("Interface2<Type1>","#x")]@@ -742,7 +748,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface2<Type2>","Interface2<#x>"),@@ -752,7 +758,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface3<Type1>","#x"),("Interface3<Type1>","#x")]@@ -760,7 +766,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface3<Type1>","#x"),("Interface3<Type2>","#x")]@@ -768,7 +774,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface3<Type1>","Interface3<#x>"),@@ -777,7 +783,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceFail tm           [("#x",[])] ["#x"]           [("Interface3<Type1>","Interface3<#x>"),@@ -786,16 +792,17 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts-        checkInferenceFail tm+        tm <- includeNewTypes emptyCategoryMap ts+        checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Type1","#x"),            ("Interface1<Type2>","Interface1<#x>"),-           ("Interface2<Type0>","Interface2<#x>")]),+           ("Interface2<Type0>","Interface2<#x>")]+           [("#x","Type1")]),     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface3<Type2>","Interface3<#x>"),@@ -806,7 +813,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface1<Type1>","Interface1<[#x|Interface2<#x>]>")]@@ -814,7 +821,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface1<Type2>","Interface1<[#x&Type1]>")]@@ -822,7 +829,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface2<Type1>","Interface2<[#x&Interface2<#x>]>")]@@ -830,7 +837,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface2<Type0>","Interface2<[#x|Type1]>")]@@ -839,7 +846,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           -- Guesses are both Type0 and Type1, and Type0 is more general.@@ -849,7 +856,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           -- An unrelated union shouldn't cause problems.@@ -859,7 +866,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[]),("#y",[])] ["#x","#y"]           [("Interface3<Type0>","[Interface1<#x>&Interface3<#x>]"),@@ -869,7 +876,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface1<any>","Interface1<#x>")]@@ -877,7 +884,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface2<all>","Interface2<#x>")]@@ -886,7 +893,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface1<all>","Interface1<#x>")]@@ -894,7 +901,7 @@     checkOperationSuccess       ("testfiles" </> "inference.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("Interface2<any>","Interface2<#x>")]@@ -903,7 +910,7 @@     checkOperationSuccess       ("testfiles" </> "delayed_merging.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceFail tm           [("#x",[])] ["#x"]           -- Guesses are either Type1 or Type2.@@ -911,7 +918,7 @@     checkOperationSuccess       ("testfiles" </> "delayed_merging.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           -- Failure to merge Type1 and Type2 is resolved by Base.@@ -922,7 +929,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("[Interface2<Type1>|Interface3<Type2>]","Interface0<#x>")]@@ -931,7 +938,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("[Interface2<Type0>|Interface3<Type4>]","Interface0<#x>")]@@ -940,7 +947,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("[Interface2<Type1>&Interface3<Type2>]","Interface0<#x>")]@@ -949,7 +956,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceFail tm           [("#x",[])] ["#x"]           -- Guesses are Type0 or Type4, which can't be merged.@@ -957,7 +964,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("[Interface2<Type1>|Interface3<Type2>]","Interface1<#x>")]@@ -966,7 +973,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("[Interface2<Type0>|Interface3<Type4>]","Interface1<#x>")]@@ -975,7 +982,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",[])] ["#x"]           [("[Interface2<Type1>&Interface3<Type2>]","Interface1<#x>")]@@ -984,7 +991,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceFail tm           [("#x",[])] ["#x"]           -- Guesses are Type0 or Type4, which can't be merged.@@ -993,7 +1000,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",["requires Type0"])] ["#x"]           -- Guesses are Type1 or Type4, which can't be merged, but the filter@@ -1003,7 +1010,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",["allows Type2"])] ["#x"]           -- Guesses are Type1 or Type4, which can't be merged, but the filter@@ -1013,7 +1020,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",["defines Defined<#x>"])] ["#x"]           -- Guesses are Type1 or Type4, which can't be merged, but the filter@@ -1024,7 +1031,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",["requires Type0"])] ["#x"]           [("[Type1|Type2]","#x")]@@ -1032,7 +1039,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceSuccess tm           [("#x",["requires #x"])] ["#x"]           [("[Type1|Type2]","#x")]@@ -1040,7 +1047,7 @@     checkOperationSuccess       ("testfiles" </> "infer_meta.0rx")       (\ts -> do-        tm <- includeNewTypes defaultCategories ts+        tm <- includeNewTypes emptyCategoryMap ts         checkInferenceFail tm           [("#x",["requires Type0"])] ["#x"]           [("[Type1|Type4]","#x")])@@ -1060,7 +1067,7 @@  getTypeRefines :: Show c => [AnyCategory c] -> String -> String -> TrackedErrors [String] getTypeRefines ts s n = do-  ta <- declareAllTypes defaultCategories ts+  ta <- declareAllTypes emptyCategoryMap ts   let r = CategoryResolver ta   t <- readSingle "(string)" s   Positional rs <- trRefines r t (CategoryName n)@@ -1068,7 +1075,7 @@  getTypeDefines :: Show c => [AnyCategory c] -> String -> String -> TrackedErrors [String] getTypeDefines ts s n = do-  ta <- declareAllTypes defaultCategories ts+  ta <- declareAllTypes emptyCategoryMap ts   let r = CategoryResolver ta   t <- readSingle "(string)" s   Positional ds <- trDefines r t (CategoryName n)@@ -1076,14 +1083,14 @@  getTypeVariance :: Show c => [AnyCategory c] -> String -> TrackedErrors [Variance] getTypeVariance ts n = do-  ta <- declareAllTypes defaultCategories ts+  ta <- declareAllTypes emptyCategoryMap ts   let r = CategoryResolver ta   (Positional vs) <- trVariance r (CategoryName n)   return vs  getTypeFilters :: Show c => [AnyCategory c] -> String -> TrackedErrors [[String]] getTypeFilters ts s = do-  ta <- declareAllTypes defaultCategories ts+  ta <- declareAllTypes emptyCategoryMap ts   let r = CategoryResolver ta   t <- readSingle "(string)" s   Positional vs <- trTypeFilters r t@@ -1091,7 +1098,7 @@  getTypeDefinesFilters :: Show c => [AnyCategory c] -> String -> TrackedErrors [[String]] getTypeDefinesFilters ts s = do-  ta <- declareAllTypes defaultCategories ts+  ta <- declareAllTypes emptyCategoryMap ts   let r = CategoryResolver ta   t <- readSingle "(string)" s   Positional vs <- trDefinesFilters r t@@ -1099,13 +1106,13 @@  scrapeAllRefines :: [AnyCategory c] -> [(String, String)] scrapeAllRefines = map (show *** show) . concat . map scrapeSingle where-  scrapeSingle (ValueInterface _ _ n _ _ rs _)    = map ((,) n . vrType) rs-  scrapeSingle (ValueConcrete _ _ n _ _ rs _ _ _) = map ((,) n . vrType) rs+  scrapeSingle (ValueInterface _ _ n _ _ rs _)      = map ((,) n . vrType) rs+  scrapeSingle (ValueConcrete _ _ n _ _ _ rs _ _ _) = map ((,) n . vrType) rs   scrapeSingle _ = []  scrapeAllDefines :: [AnyCategory c] -> [(String, String)] scrapeAllDefines = map (show *** show) . concat . map scrapeSingle where-  scrapeSingle (ValueConcrete _ _ n _ _ _ ds _ _) = map ((,) n . vdType) ds+  scrapeSingle (ValueConcrete _ _ n _ _ _ _ ds _ _) = map ((,) n . vdType) ds   scrapeSingle _ = []  checkPaired :: Show a => (a -> a -> TrackedErrors ()) -> [a] -> [a] -> TrackedErrors ()@@ -1129,6 +1136,20 @@   return $ check (parsed >>= o >> return ())   where     check x = x <!! "Check " ++ f ++ ":"++checkOperationFailWith :: String -> String -> ([AnyCategory SourceContext] -> TrackedErrors a) -> IO (TrackedErrors ())+checkOperationFailWith m f o = do+  contents <- loadFile f+  let parsed = readMulti f contents :: TrackedErrors [AnyCategory SourceContext]+  return $ check (parsed >>= o >> return ())+  where+    check c+      | isCompilerError c = do+          let text = show (getCompilerError c)+          when (not $ text =~ m) $+            compilerErrorM $ "Expected pattern " ++ show m ++ " in error output but got\n" ++ text+      | otherwise = compilerErrorM $ "Check " ++ f ++ ": Expected failure but got\n" +++                                     show (getCompilerSuccess c) ++ "\n"  checkOperationFail :: String -> ([AnyCategory SourceContext] -> TrackedErrors a) -> IO (TrackedErrors ()) checkOperationFail f o = do
src/Test/testfiles/allows_variance_left.0rx view
@@ -1,4 +1,4 @@-@value interface Interface {}+@value interface Interface { }  concrete Type<|#x> {   #x allows Interface
src/Test/testfiles/allows_variance_right.0rx view
@@ -1,4 +1,4 @@-@value interface Interface<|#x> {}+@value interface Interface<|#x> { }  concrete Type<#x|> {   #x allows Interface<#x>
src/Test/testfiles/ambiguous_merge_inherit.0rx view
@@ -1,4 +1,4 @@-@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1
src/Test/testfiles/bad_type_arg_variance.0rx view
@@ -1,4 +1,4 @@-@value interface Type1<#x|> {}+@value interface Type1<#x|> { }  @type interface Type2<#x|> {   // contravariant * contravariant = covariant
src/Test/testfiles/bad_type_return_variance.0rx view
@@ -1,4 +1,4 @@-@value interface Type1<#x|> {}+@value interface Type1<#x|> { }  @type interface Type2<|#x> {   something () -> (Type1<#x>)
src/Test/testfiles/bad_value_arg_variance.0rx view
@@ -1,4 +1,4 @@-@value interface Type1<#x|> {}+@value interface Type1<#x|> { }  @value interface Type2<#x|> {   // contravariant * contravariant = covariant
src/Test/testfiles/bad_value_return_variance.0rx view
@@ -1,4 +1,4 @@-@value interface Type1<#x|> {}+@value interface Type1<#x|> { }  @value interface Type2<|#x> {   something () -> (Type1<#x>)
src/Test/testfiles/basic_crash_test.0rt view
@@ -1,5 +1,5 @@ testcase "basic crash test" {-  crash+  failure   require "pattern in output 1"   exclude "pattern not in output 1"   require "pattern in output 2"
src/Test/testfiles/concrete.0rx view
@@ -1,23 +1,29 @@-concrete/*!!!*/Type<#a,#b // <- contravariant params-             |#c,#d // <- invariant params-             |#e,#f /* <- covariant params*/> {+concrete/*!!!*/Type<#a, #b // <- contravariant params+             |#c, #d // <- invariant params+             |#e, #f /* <- covariant params*/> {   refines /* <- used with value interfaces */ Parent-  refines Other<Type2<#a>,#f>-  defines /* <- used with type interfaces */ Equals<Type<#a,#b,#c,#d,#e,#f>>+  refines Other<Type2<#a>, #f>+  defines /* <- used with type interfaces */ Equals<Type<#a, #b, #c, #d, #e, #f>>   #a allows /* <- used with value-interface filters */ Parent   #b requires Type2<#a>   #c defines // <- used with type-interface filters     Equals<#c /* <- a type arg */> +  visibility _+   @category create<#x>     #x requires Type1<Type3>   () -> (optional Type1<Type3>) +  visibility #self+   @type create2<#y>     #y requires #x     #y allows T2     #y defines T3   () -> (optional #x)++  visibility Append<String>    @value get () -> (Type1<Type3>)   @value set (Type1<Type3>) -> ()
src/Test/testfiles/concrete_defines_concrete.0rx view
@@ -1,4 +1,4 @@-concrete Parent {}+concrete Parent { }  concrete Child {   defines Parent
src/Test/testfiles/concrete_defines_instance.0rx view
@@ -1,4 +1,4 @@-@type interface Parent {}+@type interface Parent { }  concrete Child {   defines Parent
src/Test/testfiles/concrete_defines_value.0rx view
@@ -1,4 +1,4 @@-@value interface Parent {}+@value interface Parent { }  concrete Child {   defines Parent
src/Test/testfiles/concrete_duplicate_param.0rx view
@@ -1,1 +1,1 @@-concrete Type<#x|#y|#x> {}+concrete Type<#x|#y|#x> { }
src/Test/testfiles/concrete_refines_concrete.0rx view
@@ -1,4 +1,4 @@-concrete Parent {}+concrete Parent { }  concrete Child {   refines Parent
src/Test/testfiles/concrete_refines_instance.0rx view
@@ -1,4 +1,4 @@-@type interface Parent {}+@type interface Parent { }  concrete Child {   refines Parent
src/Test/testfiles/concrete_refines_value.0rx view
@@ -1,4 +1,4 @@-@value interface Parent {}+@value interface Parent { }  concrete Child {   refines Parent
src/Test/testfiles/conflict_in_preserved.0rx view
@@ -1,4 +1,4 @@-@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1
src/Test/testfiles/contravariant_defines_covariant.0rx view
@@ -1,4 +1,4 @@-@type interface Object1<|#x> {}+@type interface Object1<|#x> { }  concrete Object2<#y|> {   defines Object1<#y>
src/Test/testfiles/contravariant_defines_invariant.0rx view
@@ -1,6 +1,6 @@-@value interface Object1<#x|> {}+@value interface Object1<#x|> { } -@type interface Object2<#z> {}+@type interface Object2<#z> { }  concrete Object3<#y|> {   // Despite matching variance with Object1, Object2 turns it into invariant.
src/Test/testfiles/contravariant_refines_covariant.0rx view
@@ -1,4 +1,4 @@-@value interface Object1<|#x> {}+@value interface Object1<|#x> { }  @value interface Object2<#y|> {   refines Object1<#y>
src/Test/testfiles/contravariant_refines_invariant.0rx view
@@ -1,6 +1,6 @@-@value interface Object1<#x|> {}+@value interface Object1<#x|> { } -@value interface Object2<#z> {}+@value interface Object2<#z> { }  @value interface Object3<#y|> {   // Despite matching variance with Object1, Object2 turns it into invariant.
src/Test/testfiles/covariant_defines_contravariant.0rx view
@@ -1,4 +1,4 @@-@type interface Object1<#x|> {}+@type interface Object1<#x|> { }  concrete Object2<|#y> {   defines Object1<#y>
src/Test/testfiles/covariant_defines_invariant.0rx view
@@ -1,6 +1,6 @@-@value interface Object1<|#x> {}+@value interface Object1<|#x> { } -@type interface Object2<#z> {}+@type interface Object2<#z> { }  concrete Object3<|#y> {   // Despite matching variance with Object1, Object2 turns it into invariant.
src/Test/testfiles/covariant_refines_contravariant.0rx view
@@ -1,4 +1,4 @@-@value interface Object1<#x|> {}+@value interface Object1<#x|> { }  @value interface Object2<|#y> {   refines Object1<#y>
src/Test/testfiles/covariant_refines_invariant.0rx view
@@ -1,6 +1,6 @@-@value interface Object1<|#x> {}+@value interface Object1<|#x> { } -@value interface Object2<#z> {}+@value interface Object2<#z> { }  @value interface Object3<|#y> {   // Despite matching variance with Object1, Object2 turns it into invariant.
src/Test/testfiles/defines_variance_left.0rx view
@@ -1,4 +1,4 @@-@type interface Interface {}+@type interface Interface { }  concrete Type<#x|> {   #x defines Interface
src/Test/testfiles/defines_variance_right.0rx view
@@ -1,4 +1,4 @@-@type interface Interface<|#x> {}+@type interface Interface<|#x> { }  concrete Type<|#x> {   #x defines Interface<#x>
src/Test/testfiles/delayed_merging.0rx view
@@ -1,4 +1,4 @@-@value interface Base {}+@value interface Base { }  concrete Type1 {   refines Base@@ -8,9 +8,9 @@   refines Base } -@value interface Interface1<|#x> {}+@value interface Interface1<|#x> { } -@value interface Interface2<|#x> {}+@value interface Interface2<|#x> { }  concrete Type {   refines Interface1<Type1>
src/Test/testfiles/duplicate_define.0rx view
@@ -1,10 +1,10 @@-@value interface Value0 {}+@value interface Value0 { }  @value interface Value1 {   refines Value0 } -@type interface Type0<|#x> {}+@type interface Type0<|#x> { }  concrete Object {   defines Type0<Value0>
src/Test/testfiles/duplicate_refine.0rx view
@@ -1,10 +1,10 @@-@value interface Value0 {}+@value interface Value0 { }  @value interface Value1 {   refines Value0 } -@value interface Value2<|#x> {}+@value interface Value2<|#x> { }  concrete Object {   refines Value2<Value0>
src/Test/testfiles/failed_merge.0rx view
@@ -1,4 +1,4 @@-@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1
src/Test/testfiles/failed_merge_params.0rx view
@@ -1,4 +1,4 @@-@value interface Type1<#a> {}+@value interface Type1<#a> { }  @value interface Type2<#b> {   refines Type1<#b>@@ -9,14 +9,14 @@ }  @value interface Interface1<#j> {-  something<#x,#y>+  something<#x, #y>     #x requires Type2<#j>     #y allows Type1<#j>   (#x) -> (#y) }  @value interface Interface2<#k> {-  something<#w,#z>+  something<#w, #z>     #w requires Type3<#k>     #z allows Type3<#k>   (#w) -> (#z)@@ -26,7 +26,7 @@   refines Interface1<#q>   refines Interface2<#q> -  @value something<#r,#s>+  @value something<#r, #s>     #r requires Type2<#q>     #s allows Type2<#q>   (#r) -> (#s)
src/Test/testfiles/filters.0rx view
@@ -1,16 +1,16 @@-@type interface Equals<#x|> {}+@type interface Equals<#x|> { } -@value interface Function<#y|#z> {}+@value interface Function<#y|#z> { } -concrete Value0<#t,#w> {+concrete Value0<#t, #w> {   #t allows #w-  #t requires Function<#t,#w>+  #t requires Function<#t, #w>   #w requires #t   #w defines Equals<#w> }  @value interface Value1 {-  refines Function<Value1,Value2>+  refines Function<Value1, Value2> }  concrete Value2 {
src/Test/testfiles/flatten.0rx view
@@ -1,15 +1,15 @@-@value interface Object1<#x,#y> {+@value interface Object1<#x, #y> {   refines Object3<#y>   // -> refines Object2 } -@value interface Object2 {}+@value interface Object2 { } -@type interface Type<#x> {}+@type interface Type<#x> { }  concrete Child {   refines Parent<Child>-  // -> refines Object1<Child,Object3<Object2>>+  // -> refines Object1<Child, Object3<Object2>>   // -> refines Object3<Object3<Object2>>   // -> refines Object2 @@ -17,7 +17,7 @@ }  @value interface Parent<#x> {-  refines Object1<#x,Object3<Object2>>+  refines Object1<#x, Object3<Object2>>   // -> refines Object3<Object3<Object2>>   // -> refines Object2 }
src/Test/testfiles/function_allows_missed.0rx view
@@ -1,8 +1,8 @@-@type interface Type1 {}+@type interface Type1 { } -@value interface Type2 {}+@value interface Type2 { } -@value interface Type3 {}+@value interface Type3 { }  concrete Type4<#x> {   #x requires Type2
src/Test/testfiles/function_bad_allows_variance.0rx view
@@ -1,4 +1,4 @@-@value interface Interface<#x|> {}+@value interface Interface<#x|> { }  concrete Type<|#x> {   @value something<#y>
src/Test/testfiles/function_bad_defines_variance.0rx view
@@ -1,4 +1,4 @@-@type interface Interface<|#x> {}+@type interface Interface<|#x> { }  concrete Type<|#x> {   @value something<#y>
src/Test/testfiles/function_bad_requires_variance.0rx view
@@ -1,4 +1,4 @@-@value interface Interface<|#x> {}+@value interface Interface<|#x> { }  concrete Type<|#x> {   @value something<#y>
src/Test/testfiles/function_defines_missed.0rx view
@@ -1,8 +1,8 @@-@type interface Type1 {}+@type interface Type1 { } -@value interface Type2 {}+@value interface Type2 { } -@value interface Type3 {}+@value interface Type3 { }  concrete Type4<#x> {   #x requires Type2
src/Test/testfiles/function_duplicate_param.0rx view
@@ -1,4 +1,4 @@ concrete Type {-  @value something<#x,#x>+  @value something<#x, #x>   () -> () }
src/Test/testfiles/function_filter_type_param.0rx view
@@ -1,11 +1,11 @@-@value interface Base1 {}+@value interface Base1 { } -@type interface Base2 {}+@type interface Base2 { }  concrete Type<#x|#y|#z> {   @type call     #x allows Base1     #y requires Base1     #z defines Base2-  (#x,#y) -> (#y,#z)+  (#x, #y) -> (#y, #z) }
src/Test/testfiles/function_filters_satisfied.0rx view
@@ -1,23 +1,23 @@-@type interface Type1<#x> {}+@type interface Type1<#x> { } -@value interface Type2<#x|> {}+@value interface Type2<#x|> { } -@value interface Type3<#x|> {}+@value interface Type3<#x|> { } -concrete Type4<#w,#x> {+concrete Type4<#w, #x> {   #w requires Type2<#w>   #x allows Type3<#x>   #w defines Type1<#w> -  @type something<#y,#z>+  @type something<#y, #z>     #y requires Type2<#y>     #z allows Type3<#z>     #y defines Type1<#y>-  () -> (Type4<#y,#z>)+  () -> (Type4<#y, #z>) -  @type something2<#y,#z>+  @type something2<#y, #z>     #y requires #w     #z allows #x     #y defines Type1<#y>-  () -> (Type4<#y,#z>)+  () -> (Type4<#y, #z>) }
src/Test/testfiles/function_requires_missed.0rx view
@@ -1,8 +1,8 @@-@type interface Type1 {}+@type interface Type1 { } -@value interface Type2 {}+@value interface Type2 { } -@value interface Type3 {}+@value interface Type3 { }  concrete Type4<#x> {   #x requires Type2
src/Test/testfiles/infer_meta.0rx view
@@ -1,4 +1,4 @@-@value interface Type0 {}+@value interface Type0 { }  @value interface Type1 {   refines Type0@@ -12,11 +12,11 @@   defines Defined<Type4> } -@type interface Defined<#x> {}+@type interface Defined<#x> { } -@value interface Interface0<|#x> {}+@value interface Interface0<|#x> { } -@value interface Interface1<#y|> {}+@value interface Interface1<#y|> { }  @value interface Interface2<#y> {   refines Interface0<#y>
src/Test/testfiles/inference.0rx view
@@ -1,14 +1,14 @@-@value interface Interface1<|#x> {}+@value interface Interface1<|#x> { } -@value interface Interface2<#y|> {}+@value interface Interface2<#y|> { }  @value interface Interface3<#z> {   refines Interface1<Type1> } -@value interface Interface4<#x|#y|#z> {}+@value interface Interface4<#x|#y|#z> { } -@value interface Type0 {}+@value interface Type0 { }  @value interface Type1 {   refines Type0
src/Test/testfiles/inherit_incompatible.0rx view
@@ -1,4 +1,4 @@-@value interface Base {}+@value interface Base { }  @value interface Child1 {   refines Base@@ -8,7 +8,7 @@   refines Base } -@value interface Inherit<#x|> {}+@value interface Inherit<#x|> { }  @value interface Parent1 {   refines Inherit<Child1>
src/Test/testfiles/internal.0rx view
@@ -1,5 +1,5 @@ $TestsOnly$ -concrete Type {}+concrete Type { } -define Type {}+define Type { }
src/Test/testfiles/invariant_self.0rx view
@@ -1,4 +1,4 @@-@value interface Base<#x> {}+@value interface Base<#x> { }  @value interface Value<#x|#y|#z> {   refines Base<#self>
src/Test/testfiles/merge_incompatible.0rx view
@@ -1,4 +1,4 @@-@value interface Base {}+@value interface Base { }  @value interface Child1 {   refines Base@@ -8,7 +8,7 @@   refines Base } -@value interface Inherit<#x|> {}+@value interface Inherit<#x|> { }  @value interface Parent1 {   refines Inherit<Child1>
src/Test/testfiles/merged.0rx view
@@ -1,4 +1,4 @@-@value interface Value0 {}+@value interface Value0 { }  @value interface Value1 {   refines Value0@@ -12,16 +12,16 @@   refines Value0 } -@value interface Value4<#x|#y> {}+@value interface Value4<#x|#y> { } -@type interface Type0<#x|#y> {}+@type interface Type0<#x|#y> { }  @value interface Inherit1 {-  refines Value4<Value1,Value1>+  refines Value4<Value1, Value1> }  @value interface Inherit2 {-  refines Value4<Value2,Value0>+  refines Value4<Value2, Value0> }  concrete Test {
src/Test/testfiles/partial_params.0rx view
@@ -1,3 +1,3 @@ concrete Child<#x|#y> {-  refines Parent<#x,#y>+  refines Parent<#x, #y> }
src/Test/testfiles/preserve_merged.0rx view
@@ -1,4 +1,4 @@-@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1
src/Test/testfiles/procedures.0rx view
@@ -1,4 +1,4 @@-testFunction1 (a,b,c) (d,e,f) {+testFunction1 (a, b, c) (d, e, f) {   if (T.f()) {     // do nothing   } elif (#q.r().f()) {@@ -7,12 +7,12 @@     // sleep   } -  x <- Type<#z,T<#m>>{ r, Type.new() }+  x <- Type<#z, T<#m>>{ r, Type.new() }    x <- empty    scoped {-    optional T myvar <- reduce<#x,#y>(q)+    optional T myvar <- reduce<#x, #y>(q)   } in if (present(myvar)) {     \ unqualified()   } else {@@ -20,7 +20,7 @@   }    scoped {-    optional T myvar <- reduce<#x,#y>(q)+    optional T myvar <- reduce<#x, #y>(q)   } in v, _ <- x.process(myvar)    scoped {@@ -30,7 +30,7 @@   } in \ x.process()    \ z.call().call()-  x, weak [#k|Type] y, _ <- z.call()+  x, weak [#k | Type] y, _ <- z.call()   x <- z?T<#z>.call().call()   return _   return a@@ -44,4 +44,4 @@   } } -testFunction2 (a,b,c) {}+testFunction2 (a, b, c) { }
src/Test/testfiles/public.0rp view
@@ -1,4 +1,4 @@ $ModuleOnly$ $TestsOnly$ -concrete Type {}+concrete Type { }
src/Test/testfiles/refine_wrong_direction.0rx view
@@ -1,10 +1,10 @@-@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1 } -@value interface Inherited<|#x> {}+@value interface Inherited<|#x> { }  @value interface Parent {   refines Inherited<Type2>
src/Test/testfiles/requires_variance_left.0rx view
@@ -1,4 +1,4 @@-@value interface Interface {}+@value interface Interface { }  concrete Type<#x|> {   #x requires Interface
src/Test/testfiles/requires_variance_right.0rx view
@@ -1,4 +1,4 @@-@value interface Interface<|#x> {}+@value interface Interface<|#x> { }  concrete Type<|#x> {   #x requires Interface<#x>
src/Test/testfiles/resolved_in_preserved.0rx view
@@ -1,4 +1,4 @@-@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1
src/Test/testfiles/successful_merge.0rx view
@@ -1,4 +1,4 @@-@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1
src/Test/testfiles/successful_merge_params.0rx view
@@ -1,4 +1,4 @@-@value interface Type1<#a> {}+@value interface Type1<#a> { }  @value interface Type2<#b> {   refines Type1<#b>@@ -9,14 +9,14 @@ }  @value interface Interface1<#j> {-  something<#x,#y>+  something<#x, #y>     #x requires Type2<#j>     #y allows Type1<#j>   (#x) -> (#y) }  @value interface Interface2<#k> {-  something<#w,#z>+  something<#w, #z>     #w requires Type3<#k>     #z allows Type1<#k>   (#w) -> (#z)@@ -26,7 +26,7 @@   refines Interface1<#q>   refines Interface2<#q> -  @value something<#r,#s>+  @value something<#r, #s>     #r requires Type2<#q>     #s allows Type2<#q>   (#r) -> (#s)
src/Test/testfiles/test.0rt view
@@ -11,5 +11,5 @@ }  define Test {-  run () {}+  run () { } }
src/Test/testfiles/type_duplicate_param.0rx view
@@ -1,1 +1,1 @@-@type interface Type<#x|#y|#x> {}+@type interface Type<#x|#y|#x> { }
src/Test/testfiles/type_interface.0rx view
@@ -1,4 +1,4 @@-@type interface Type<#a,#b|#c,#d|#e,#f> {+@type interface Type<#a, #b|#c, #d|#e, #f> {   create () -> (optional #x)    create2<#y>
src/Test/testfiles/valid_filter_variance.0rx view
@@ -1,16 +1,16 @@-@value interface Interface1<#x|> {}+@value interface Interface1<#x|> { }  concrete Type1<#x|> {   #x allows Interface1<#x> } -@type interface Interface2<#x|> {}+@type interface Interface2<#x|> { }  concrete Type2<|#x> {   #x defines Interface2<#x> } -@value interface Interface3<#x|> {}+@value interface Interface3<#x|> { }  concrete Type3<|#x> {   #x requires Interface3<#x>
src/Test/testfiles/valid_function_variance.0rx view
@@ -1,4 +1,4 @@-@value interface Type1<#x|> {}+@value interface Type1<#x|> { }  @value interface Type2<#x|> {   // arg:    contravariant * contravariant * contravariant = contravariant
src/Test/testfiles/valid_self.0rx view
@@ -1,4 +1,4 @@-@value interface Base<|#x> {}+@value interface Base<|#x> { }  @value interface Value<#x|#y|#z> {   refines Base<#self>@@ -6,11 +6,11 @@ }  concrete Child1 {-  refines Value<all,all,all>+  refines Value<all, all, all>   @value call () -> (#self) }  concrete Child2 {-  refines Value<all,all,all>+  refines Value<all, all, all>   @value call () -> (all) }
src/Test/testfiles/valid_variances.0rx view
@@ -1,6 +1,6 @@-@value interface Object1<#x|> {}+@value interface Object1<#x|> { } -@value interface Object2<|#y> {}+@value interface Object2<|#y> { }  @value interface Object3<#w|#z> {   refines Object1<#w>@@ -8,7 +8,7 @@ }  @value interface Object4<#t> {-  refines Object3<#t,#t>+  refines Object3<#t, #t> }  @value interface Object5<|#q> {@@ -16,7 +16,7 @@   refines Object1<Object1<#q>> } -@type interface Object6<|#x> {}+@type interface Object6<|#x> { }  concrete Object7<|#s> {   // Variance reversed twice by Object1.
src/Test/testfiles/value_duplicate_param.0rx view
@@ -1,1 +1,1 @@-@value interface Type<#x|#y|#x> {}+@value interface Type<#x|#y|#x> { }
src/Test/testfiles/value_interface.0rx view
@@ -1,6 +1,6 @@-@value interface Type<#a,#b|#c,#d|#e,#f> {+@value interface Type<#a, #b|#c, #d|#e, #f> {   refines Parent-  refines Other<Type2<#a>,#f>+  refines Other<Type2<#a>, #f>    get () -> (#x)   set (#x) -> ()
src/Test/testfiles/value_refines_concrete.0rx view
@@ -1,4 +1,4 @@-concrete Parent {}+concrete Parent { }  @value interface Child {   refines Parent
src/Test/testfiles/value_refines_instance.0rx view
@@ -1,4 +1,4 @@-@type interface Parent {}+@type interface Parent { }  @value interface Child {   refines Parent
src/Test/testfiles/value_refines_value.0rx view
@@ -1,4 +1,4 @@-@value interface Parent {}+@value interface Parent { }  @value interface Child {   refines Parent
src/Types/Builtin.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -16,6 +16,7 @@  -- Author: Kevin P. Barry [ta0kira@gmail.com] +{-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-}  module Types.Builtin (@@ -23,29 +24,26 @@   PrimitiveType(..),   boolRequiredValue,   charRequiredValue,-  defaultCategories,   emptyType,   floatRequiredValue,   formattedRequiredValue,   intRequiredValue,+  isIdentifierRequiredValue,   isPointerRequiredValue,   isOpaqueMulti,   orderOptionalValue,+  requiredStaticTypes,   stringRequiredValue, ) where -import qualified Data.Map as Map+import qualified Data.Set as Set  import Base.GeneralType import Base.MergeTree (reduceMergeTree) import Base.Positional-import Types.TypeCategory import Types.TypeInstance  -defaultCategories :: CategoryMap c-defaultCategories = Map.empty- boolRequiredValue :: ValueType boolRequiredValue = requiredSingleton BuiltinBool stringRequiredValue :: ValueType@@ -68,6 +66,13 @@   extractSingle = reduceMergeTree (const Nothing) (const Nothing) Just isPointerRequiredValue _ = False +isIdentifierRequiredValue :: ValueType -> Bool+isIdentifierRequiredValue (ValueType RequiredValue t) = check $ extractSingle t where+  check (Just (JustTypeInstance (TypeInstance BuiltinIdentifier (Positional [_])))) = True+  check _ = False+  extractSingle = reduceMergeTree (const Nothing) (const Nothing) Just+isIdentifierRequiredValue _ = False+ emptyType :: ValueType emptyType = ValueType OptionalValue minBound @@ -77,7 +82,8 @@   PrimInt |   PrimFloat |   PrimString |-  PrimPointer+  PrimPointer |+  PrimIdentifier   deriving (Eq,Show)  data ExpressionValue =@@ -98,3 +104,19 @@ isOpaqueMulti :: ExpressionValue -> Bool isOpaqueMulti (OpaqueMulti _) = True isOpaqueMulti _               = False++requiredStaticTypes :: Set.Set CategoryName+#ifdef darwin_HOST_OS+-- Weak linking doesn't work on MacOS, so we need these in order to link against+-- boxed.cpp without linker errors.+requiredStaticTypes = Set.fromList [+    BuiltinBool,+    BuiltinChar,+    BuiltinInt,+    BuiltinFloat,+    BuiltinPointer,+    BuiltinIdentifier+  ]+#else+requiredStaticTypes = Set.empty+#endif
src/Types/DefinedCategory.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -143,12 +143,12 @@   foldr (update fm) (return start) fs where   start = Map.fromList $ map (\f -> (sfName f,f)) $ getCategoryFunctions t   pm = getCategoryParamMap t-  update fm f@(ScopedFunction c n t2 s as rs ps fs2 ms) fa = do+  update fm f@(ScopedFunction c n t2 s v as rs ps fs2 ms) fa = do     validateCategoryFunction r t f     fa' <- fa     case n `Map.lookup` fa' of          Nothing -> return $ Map.insert n f fa'-         (Just f0@(ScopedFunction c2 _ _ _ _ _ _ _ ms2)) -> do+         (Just f0@(ScopedFunction c2 _ _ _ _ _ _ _ _ ms2)) -> do            ("In function merge:\n---\n" ++ show f0 ++              "\n  ->\n" ++ show f ++ "\n---\n") ??> do               f0' <- parsedToFunctionType f0@@ -156,7 +156,7 @@               case s of                    CategoryScope -> checkFunctionConvert r Map.empty Map.empty f0' f'                    _             -> checkFunctionConvert r fm pm f0' f'-           return $ Map.insert n (ScopedFunction (c++c2) n t2 s as rs ps fs2 ([f0]++ms++ms2)) fa'+           return $ Map.insert n (ScopedFunction (c++c2) n t2 s v as rs ps fs2 ([f0]++ms++ms2)) fa'  pairProceduresToFunctions :: (Show c, CollectErrorsM m) =>   Map.Map FunctionName (ScopedFunction c) -> [ExecutableProcedure c] ->@@ -189,7 +189,7 @@                      formatFullContextBrace (epContext p) ++                      " does not correspond to a function"     getPair (Just f) (Just p) = do-      processPairs_ alwaysPair (fmap pvType $ sfArgs f) (fmap inputValueName $ avNames $ epArgs p) <!!+      processPairs_ alwaysPair (fmap (pvType . fst) $ sfArgs f) (fmap inputValueName $ avNames $ epArgs p) <!!         ("Procedure for " ++ show (sfName f) ++          formatFullContextBrace (avContext $ epArgs p) ++          " has the wrong number of arguments" ++@@ -229,13 +229,13 @@ -- TODO: Most of this duplicates parts of flattenAllConnections. mergeInternalInheritance :: (Show c, CollectErrorsM m) =>   CategoryMap c -> DefinedCategory c -> m (CategoryMap c)-mergeInternalInheritance tm d = "In definition of " ++ show (dcName d) ++ formatFullContextBrace (dcContext d) ??> do+mergeInternalInheritance cm@(CategoryMap km tm) d = "In definition of " ++ show (dcName d) ++ formatFullContextBrace (dcContext d) ??> do   let rs2 = dcRefines d   let ds2 = dcDefines d-  (_,t@(ValueConcrete c ns n pg ps rs ds vs fs)) <- getConcreteCategory tm (dcContext d,dcName d)-  let c2 = ValueConcrete c ns n pg ps (rs++rs2) (ds++ds2) vs fs+  (_,t@(ValueConcrete c ns n pg fv ps rs ds vs fs)) <- getConcreteCategory cm (dcContext d,dcName d)+  let c2 = ValueConcrete c ns n pg fv ps (rs++rs2) (ds++ds2) vs fs   let tm' = Map.insert (dcName d) c2 tm-  let r = CategoryResolver tm'+  let r = CategoryResolver (CategoryMap km tm')   fm <- getCategoryFilterMap t   let pm = getCategoryParamMap t   rs2' <- fmap concat $ mapCompilerM (flattenRefine r) rs2@@ -249,17 +249,17 @@   pg2 <- fmap concat $ mapCompilerM getRefinesPragmas rs2   pg3 <- fmap concat $ mapCompilerM getDefinesPragmas ds2   let fs2 = mergeInternalFunctions fs (dcFunctions d)-  fs' <- mergeFunctions r tm' pm fm rs' ds' fs2-  let c2' = ValueConcrete c ns n (pg++pg2++pg3) ps rs' ds' vs fs'+  fs' <- mergeFunctions r (CategoryMap km tm') pm fm rs' ds' fs2+  let c2' = ValueConcrete c ns n (pg++pg2++pg3) fv ps rs' ds' vs fs'   let tm0 = (dcName d) `Map.delete` tm-  checkCategoryInstances tm0 [c2']-  return $ Map.insert (dcName d) c2' tm+  checkCategoryInstances (CategoryMap km tm0) [c2']+  return $ CategoryMap km $ Map.insert (dcName d) c2' tm   where     getRefinesPragmas rf = do-      (_,t) <- getCategory tm (vrContext rf,tiName $ vrType rf)+      (_,t) <- getCategory cm (vrContext rf,tiName $ vrType rf)       return $ map (prependCategoryPragmaContext $ vrContext rf) $ getCategoryPragmas t     getDefinesPragmas df = do-      (_,t) <- getCategory tm (vdContext df,diName $ vdType df)+      (_,t) <- getCategory cm (vdContext df,diName $ vdType df)       return $ map (prependCategoryPragmaContext $ vdContext df) $ getCategoryPragmas t     mergeInternalFunctions fs1 = Map.elems . foldr single (funcMap fs1)     funcMap = Map.fromList . map (\f -> (sfName f,f))@@ -271,6 +271,7 @@                sfName = sfName f,                sfType = sfType f,                sfScope = sfScope f,+               sfVisibility = sfVisibility f,                sfArgs = sfArgs f,                sfReturns = sfReturns f,                sfParams = sfParams f,@@ -284,7 +285,7 @@       validateDefinesVariance r vm Covariant t <??         "In " ++ show t ++ formatFullContextBrace c     flattenRefine r ra@(ValueRefine c t) = do-      (_,t2) <- getValueCategory tm (c,tiName t)+      (_,t2) <- getValueCategory cm (c,tiName t)       rs <- mapCompilerM (singleRefine r ra) (getCategoryRefines t2)       return (ra:rs)     singleRefine r (ValueRefine c t) (ValueRefine c2 t2) = do
src/Types/IntegrationTest.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2020 Kevin P. Barry+Copyright 2020,2023 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.@@ -33,6 +33,7 @@ ) where  import Types.TypeCategory+import Types.TypeInstance import Types.DefinedCategory import Types.Procedure @@ -67,11 +68,13 @@   } |   ExpectRuntimeError {     ereContext :: [c],+    ereCategory :: Maybe ([c],TypeInstance),     ereRequirePattern :: [OutputPattern],     ereExcludePattern :: [OutputPattern]   } |   ExpectRuntimeSuccess {     ersContext :: [c],+    ersCategory :: Maybe ([c],TypeInstance),     ersRequirePattern :: [OutputPattern],     ersExcludePattern :: [OutputPattern]   }@@ -94,21 +97,21 @@ isExpectCompilerError _                          = 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 (ExpectCompiles _ rs _)       = rs-getRequirePattern (ExpectCompilerError _ rs _)   = rs-getRequirePattern (ExpectRuntimeError _ rs _)   = rs-getRequirePattern (ExpectRuntimeSuccess _ rs _) = rs+getRequirePattern (ExpectCompiles _ rs _)         = rs+getRequirePattern (ExpectCompilerError _ rs _)     = rs+getRequirePattern (ExpectRuntimeError _ _ rs _)   = rs+getRequirePattern (ExpectRuntimeSuccess _ _ rs _) = rs  getExcludePattern :: ExpectedResult c -> [OutputPattern]-getExcludePattern (ExpectCompiles _ _ es)       = es-getExcludePattern (ExpectCompilerError _ _ es)   = es-getExcludePattern (ExpectRuntimeError _ _ es)   = es-getExcludePattern (ExpectRuntimeSuccess _ _ es) = es+getExcludePattern (ExpectCompiles _ _ es)         = es+getExcludePattern (ExpectCompilerError _ _ es)    = es+getExcludePattern (ExpectRuntimeError _ _ _ es)   = es+getExcludePattern (ExpectRuntimeSuccess _ _ _ es) = es
src/Types/Procedure.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2023 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.@@ -21,6 +21,7 @@ module Types.Procedure (   ArgValues(..),   Assignable(..),+  AssignmentType(..),   ExecutableProcedure(..),   Expression(..),   ExpressionStart(..),@@ -32,6 +33,7 @@   InputValue(..),   InstanceOrInferred(..),   IteratedLoop(..),+  MacroExpression(..),   MacroName(..),   Operator(..),   OutputValue(..),@@ -42,6 +44,7 @@   Statement(..),   TestProcedure(..),   TraceType(..),+  ValueCallType(..),   ValueLiteral(..),   ValueOperation(..),   VariableName(..),@@ -180,6 +183,8 @@   RawFailCall String |   IgnoreValues [c] (Expression c) |   Assignment [c] (Positional (Assignable c)) (Expression c) |+  AssignmentEmpty [c] VariableName (Expression c) |+  VariableSwap [c] (OutputValue c) (OutputValue c) |   DeferredVariables [c] [Assignable c] |   NoValueExpression [c] (VoidExpression c) |   MarkReadOnly [c] [VariableName] |@@ -203,6 +208,8 @@ getStatementContext (RawFailCall _)         = [] getStatementContext (IgnoreValues c _)      = c getStatementContext (Assignment c _ _)      = c+getStatementContext (AssignmentEmpty c _ _) = c+getStatementContext (VariableSwap c _ _)    = c getStatementContext (DeferredVariables c _) = c getStatementContext (NoValueExpression c _) = c getStatementContext (MarkReadOnly c _)      = c@@ -253,7 +260,9 @@   Literal (ValueLiteral c) |   UnaryExpression [c] (Operator c) (Expression c) |   InfixExpression [c] (Expression c) (Operator c) (Expression c) |-  RawExpression ExpressionType ExpressionValue+  RawExpression ExpressionType ExpressionValue |+  DelegatedFunctionCall [c] (FunctionSpec c) |+  DelegatedInitializeValue [c] (Maybe TypeInstance)   deriving (Show)  type ExpressionType = Positional ValueType@@ -296,25 +305,33 @@ getOperatorName (FunctionOperator _ (FunctionSpec _ _ n _)) = n  getExpressionContext :: Expression c -> [c]-getExpressionContext (Expression c _ _)        = c-getExpressionContext (Literal l)               = getValueLiteralContext l-getExpressionContext (UnaryExpression c _ _)   = c-getExpressionContext (InfixExpression c _ _ _) = c-getExpressionContext (RawExpression _ _)       = []+getExpressionContext (Expression c _ _)             = c+getExpressionContext (Literal l)                    = getValueLiteralContext l+getExpressionContext (UnaryExpression c _ _)        = c+getExpressionContext (InfixExpression c _ _ _)      = c+getExpressionContext (RawExpression _ _)            = []+getExpressionContext (DelegatedFunctionCall c _)    = c+getExpressionContext (DelegatedInitializeValue c _) = c  data FunctionCall c =-  FunctionCall [c] FunctionName (Positional (InstanceOrInferred c)) (Positional (Expression c))+  FunctionCall [c] FunctionName (Positional (InstanceOrInferred c)) (Positional (Maybe (CallArgLabel c), Expression c))   deriving (Show) +data AssignmentType =+  AlwaysAssign |+  AssignIfEmpty+  deriving (Eq,Show)+ data ExpressionStart c =   NamedVariable (OutputValue c) |   NamedMacro [c] MacroName |+  ExpressionMacro [c] MacroExpression |   CategoryCall [c] CategoryName (FunctionCall c) |   TypeCall [c] TypeInstanceOrParam (FunctionCall c) |   UnqualifiedCall [c] (FunctionCall c) |   BuiltinCall [c] (FunctionCall c) |   ParensExpression [c] (Expression c) |-  InlineAssignment [c] VariableName (Expression c) |+  InlineAssignment [c] VariableName AssignmentType (Expression c) |   InitializeValue [c] (Maybe TypeInstance) (Positional (Expression c)) |   UnambiguousLiteral (ValueLiteral c)   deriving (Show)@@ -323,22 +340,27 @@   StringLiteral [c] String |   CharLiteral [c] Char |   IntegerLiteral [c] Bool Integer |-  DecimalLiteral [c] Integer Integer |+  DecimalLiteral [c] Integer Integer Integer |   BoolLiteral [c] Bool |   EmptyLiteral [c]   deriving (Show)  getValueLiteralContext :: ValueLiteral c -> [c]-getValueLiteralContext (StringLiteral c _)    = c-getValueLiteralContext (CharLiteral c _)      = c-getValueLiteralContext (IntegerLiteral c _ _) = c-getValueLiteralContext (DecimalLiteral c _ _) = c-getValueLiteralContext (BoolLiteral c _)      = c-getValueLiteralContext (EmptyLiteral c)       = c+getValueLiteralContext (StringLiteral c _)      = c+getValueLiteralContext (CharLiteral c _)        = c+getValueLiteralContext (IntegerLiteral c _ _)   = c+getValueLiteralContext (DecimalLiteral c _ _ _) = c+getValueLiteralContext (BoolLiteral c _)        = c+getValueLiteralContext (EmptyLiteral c)         = c +data ValueCallType =+  AlwaysCall |+  CallUnlessEmpty+  deriving (Eq,Show)+ data ValueOperation c =   TypeConversion [c] GeneralInstance |-  ValueCall [c] (FunctionCall c) |+  ValueCall [c] ValueCallType (FunctionCall c) |   SelectReturn [c] Int   deriving (Show) @@ -352,6 +374,10 @@   show = mnName  data TraceType = NoTrace | TraceCreation deriving (Show)++data MacroExpression =+  MacroCallTrace+  deriving (Show)  data PragmaProcedure c =   PragmaTracing {
src/Types/TypeCategory.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2021 Kevin P. Barry+Copyright 2019-2021,2023 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.@@ -21,9 +21,11 @@  module Types.TypeCategory (   AnyCategory(..),-  CategoryMap,+  CallArgLabel(..),+  CategoryMap(..),   CategoryResolver(..),   FunctionName(..),+  FunctionVisibility(..),   Namespace(..),   ParamFilter(..),   PassedValue(..),@@ -37,8 +39,10 @@   checkCategoryInstances,   checkConnectedTypes,   checkConnectionCycles,+  checkFunctionCallVisibility,   checkParamVariances,   declareAllTypes, -- TODO: Remove?+  emptyCategoryMap,   flattenAllConnections,   formatFullContext,   formatFullContextBrace,@@ -73,6 +77,7 @@   isStaticNamespace,   isValueConcrete,   isValueInterface,+  matchesCallArgLabel,   mergeDefines,   mergeFunctions,   mergeInferredTypes,@@ -85,6 +90,7 @@   replaceSelfFunction,   setCategoryNamespace,   singleFromCategory,+  toCategoryMap,   topoSortCategories,   uncheckedSubFunction,   validateCategoryFunction,@@ -129,6 +135,7 @@     vcNamespace :: Namespace,     vcName :: CategoryName,     vcPragmas :: [PragmaCategory c],+    vcVisibility :: [FunctionVisibility c],     vcParams :: [ValueParam c],     vcRefines :: [ValueRefine c],     vcDefines :: [ValueDefine c],@@ -172,7 +179,7 @@          map (\p -> "  " ++ show p) pg ++          map (\f -> formatInterfaceFunc f) fs) ++       "\n}\n"-    format (ValueConcrete cs ns n pg ps rs ds vs fs) =+    format (ValueConcrete cs ns n pg _ ps rs ds vs fs) =       "concrete " ++ show n ++ formatParams ps ++ namespace ns ++ " { " ++ formatContext cs ++ "\n" ++       (intercalate "\n\n" $          map (\p -> "  " ++ show p) pg ++@@ -200,54 +207,59 @@     formatConcreteFunc f = showFunctionInContext (show (sfScope f) ++ " ") "  " f  getCategoryName :: AnyCategory c -> CategoryName-getCategoryName (ValueInterface _ _ n _ _ _ _)    = n-getCategoryName (InstanceInterface _ _ n _ _ _)   = n-getCategoryName (ValueConcrete _ _ n _ _ _ _ _ _) = n+getCategoryName (ValueInterface _ _ n _ _ _ _)      = n+getCategoryName (InstanceInterface _ _ n _ _ _)     = n+getCategoryName (ValueConcrete _ _ n _ _ _ _ _ _ _) = n  getCategoryContext :: AnyCategory c -> [c]-getCategoryContext (ValueInterface c _ _ _ _ _ _)    = c-getCategoryContext (InstanceInterface c _ _ _ _ _)   = c-getCategoryContext (ValueConcrete c _ _ _ _ _ _ _ _) = c+getCategoryContext (ValueInterface c _ _ _ _ _ _)      = c+getCategoryContext (InstanceInterface c _ _ _ _ _)     = c+getCategoryContext (ValueConcrete c _ _ _ _ _ _ _ _ _) = c  getCategoryNamespace :: AnyCategory c -> Namespace-getCategoryNamespace (ValueInterface _ ns _ _ _ _ _)    = ns-getCategoryNamespace (InstanceInterface _ ns _ _ _ _)   = ns-getCategoryNamespace (ValueConcrete _ ns _ _ _ _ _ _ _) = ns+getCategoryNamespace (ValueInterface _ ns _ _ _ _ _)      = ns+getCategoryNamespace (InstanceInterface _ ns _ _ _ _)     = ns+getCategoryNamespace (ValueConcrete _ ns _ _ _ _ _ _ _ _) = ns  getCategoryPragmas :: AnyCategory c -> [PragmaCategory c]-getCategoryPragmas (ValueInterface _ _ _ pg _ _ _)    = pg-getCategoryPragmas (InstanceInterface _ _ _ pg _ _)   = pg-getCategoryPragmas (ValueConcrete _ _ _ pg _ _ _ _ _) = pg+getCategoryPragmas (ValueInterface _ _ _ pg _ _ _)      = pg+getCategoryPragmas (InstanceInterface _ _ _ pg _ _)     = pg+getCategoryPragmas (ValueConcrete _ _ _ pg _ _ _ _ _ _) = pg  setCategoryNamespace :: Namespace -> AnyCategory c -> AnyCategory c-setCategoryNamespace ns (ValueInterface c _ n pg ps rs fs)      = (ValueInterface c ns n pg ps rs fs)-setCategoryNamespace ns (InstanceInterface c _ n pg ps fs)      = (InstanceInterface c ns n pg ps fs)-setCategoryNamespace ns (ValueConcrete c _ n pg ps rs ds vs fs) = (ValueConcrete c ns n pg ps rs ds vs fs)+setCategoryNamespace ns (ValueInterface c _ n pg ps rs fs)        = (ValueInterface c ns n pg ps rs fs)+setCategoryNamespace ns (InstanceInterface c _ n pg ps fs)        = (InstanceInterface c ns n pg ps fs)+setCategoryNamespace ns (ValueConcrete c _ n pg fv ps rs ds vs fs) = (ValueConcrete c ns n pg fv ps rs ds vs fs) +getCategoryVisibilities :: AnyCategory c -> [FunctionVisibility c]+getCategoryVisibilities (ValueInterface _ _ _ _ _ _ _)       = []+getCategoryVisibilities (InstanceInterface _ _ _ _ _ _)      = []+getCategoryVisibilities (ValueConcrete _ _ _ _ fv _ _ _ _ _) = fv+ getCategoryParams :: AnyCategory c -> [ValueParam c]-getCategoryParams (ValueInterface _ _ _ _ ps _ _)    = ps-getCategoryParams (InstanceInterface _ _ _ _ ps _)   = ps-getCategoryParams (ValueConcrete _ _ _ _ ps _ _ _ _) = ps+getCategoryParams (ValueInterface _ _ _ _ ps _ _)      = ps+getCategoryParams (InstanceInterface _ _ _ _ ps _)     = ps+getCategoryParams (ValueConcrete _ _ _ _ _ ps _ _ _ _) = ps  getCategoryRefines :: AnyCategory c -> [ValueRefine c]-getCategoryRefines (ValueInterface _ _ _ _ _ rs _)    = rs-getCategoryRefines (InstanceInterface _ _ _ _ _ _)    = []-getCategoryRefines (ValueConcrete _ _ _ _ _ rs _ _ _) = rs+getCategoryRefines (ValueInterface _ _ _ _ _ rs _)      = rs+getCategoryRefines (InstanceInterface _ _ _ _ _ _)      = []+getCategoryRefines (ValueConcrete _ _ _ _ _ _ rs _ _ _) = rs  getCategoryDefines :: AnyCategory c -> [ValueDefine c]-getCategoryDefines (ValueInterface _ _ _ _ _ _ _)     = []-getCategoryDefines (InstanceInterface _ _ _ _ _ _)    = []-getCategoryDefines (ValueConcrete _ _ _ _ _ _ ds _ _) = ds+getCategoryDefines (ValueInterface _ _ _ _ _ _ _)       = []+getCategoryDefines (InstanceInterface _ _ _ _ _ _)      = []+getCategoryDefines (ValueConcrete _ _ _ _ _ _ _ ds _ _) = ds  getCategoryFilters :: AnyCategory c -> [ParamFilter c]-getCategoryFilters (ValueInterface _ _ _ _ _ _ _)     = []-getCategoryFilters (InstanceInterface _ _ _ _ _ _)    = []-getCategoryFilters (ValueConcrete _ _ _ _ _ _ _ vs _) = vs+getCategoryFilters (ValueInterface _ _ _ _ _ _ _)       = []+getCategoryFilters (InstanceInterface _ _ _ _ _ _)      = []+getCategoryFilters (ValueConcrete _ _ _ _ _ _ _ _ vs _) = vs  getCategoryFunctions :: AnyCategory c -> [ScopedFunction c]-getCategoryFunctions (ValueInterface _ _ _ _ _ _ fs)    = fs-getCategoryFunctions (InstanceInterface _ _ _ _ _ fs)   = fs-getCategoryFunctions (ValueConcrete _ _ _ _ _ _ _ _ fs) = fs+getCategoryFunctions (ValueInterface _ _ _ _ _ _ fs)      = fs+getCategoryFunctions (InstanceInterface _ _ _ _ _ fs)     = fs+getCategoryFunctions (ValueConcrete _ _ _ _ _ _ _ _ _ fs) = fs  singleFromCategory :: AnyCategory c -> TypeInstance singleFromCategory t = TypeInstance n (Positional ps) where@@ -272,7 +284,7 @@   fromFilter ImmutableFilter = []   fromType (ValueType _ t2) = fromInstance t2   fromFunction f = args ++ returns ++ filters2 where-    args = concat $ map (fromType . pvType) $ pValues $ sfArgs f+    args = concat $ map (fromType . pvType . fst) $ pValues $ sfArgs f     returns = concat $ map (fromType . pvType) $ pValues $ sfReturns f     filters2 = concat $ map (fromFilter . pfFilter) $ sfFilters f @@ -285,7 +297,7 @@ isInstanceInterface _ = False  isValueConcrete :: AnyCategory c -> Bool-isValueConcrete (ValueConcrete _ _ _ _ _ _ _ _ _) = True+isValueConcrete (ValueConcrete _ _ _ _ _ _ _ _ _ _) = True isValueConcrete _ = False  data Namespace =@@ -463,18 +475,25 @@   ParamValues -> GeneralInstance -> m GeneralInstance subAllParams pa = uncheckedSubInstance (getValueForParam pa) -type CategoryMap c = Map.Map CategoryName (AnyCategory c)+data CategoryMap c =+  CategoryMap {+    cmKnown :: Map.Map CategoryName [c],+    cmAvailable :: Map.Map CategoryName (AnyCategory c)+  } +emptyCategoryMap :: CategoryMap c+emptyCategoryMap = toCategoryMap []++toCategoryMap :: [(CategoryName,AnyCategory c)] -> CategoryMap c+toCategoryMap = CategoryMap Map.empty . Map.fromList+ getCategory :: (Show c, CollectErrorsM m) =>   CategoryMap c -> ([c],CategoryName) -> m ([c],AnyCategory c)-getCategory tm (c,n) =-  case n `Map.lookup` tm of-       (Just t) -> return (c,t)-       _ -> compilerErrorM $ "Type " ++ show n ++ context ++ " not found"-  where-    context-      | null c = ""-      | otherwise = formatFullContextBrace c+getCategory (CategoryMap km tm) (c,n) = handle (n `Map.lookup` tm) (n `Map.lookup` km) where+  handle (Just t) _ = return (c,t)+  handle _ (Just c2) = compilerErrorM $ "Type " ++ show n ++ formatFullContextBrace c2 +++                                        " not visible here" ++ formatFullContextBrace c+  handle _ _ = compilerErrorM $ "Type " ++ show n ++ " not found" ++ formatFullContextBrace c  getValueCategory :: (Show c, CollectErrorsM m) =>   CategoryMap c -> ([c],CategoryName) -> m ([c],AnyCategory c)@@ -520,13 +539,13 @@ declareAllTypes :: (Show c, CollectErrorsM m) =>   CategoryMap c -> [AnyCategory c] -> m (CategoryMap c) declareAllTypes tm0 = foldr (\t tm -> tm >>= update t) (return tm0) where-  update t tm =+  update t (CategoryMap km tm) =     case getCategoryName t `Map.lookup` tm of         (Just t2) -> compilerErrorM $ "Type " ++ show (getCategoryName t) ++                                       formatFullContextBrace (getCategoryContext t) ++                                       " has already been declared" ++                                       formatFullContextBrace (getCategoryContext t2)-        _ -> return $ Map.insert (getCategoryName t) t tm+        _ -> return $ CategoryMap km $ Map.insert (getCategoryName t) t tm  getFilterMap :: CollectErrorsM m => [ValueParam c] -> [ParamFilter c] -> m ParamFilters getFilterMap ps fs = do@@ -577,20 +596,20 @@  checkConnectedTypes :: (Show c, CollectErrorsM m) =>   CategoryMap c -> [AnyCategory c] -> m ()-checkConnectedTypes tm0 ts = do-  tm <- declareAllTypes tm0 ts-  collectAllM_ (map (checkSingle tm) ts)+checkConnectedTypes cm0 ts = do+  cm <- declareAllTypes cm0 ts+  collectAllM_ (map (checkSingle cm) ts)   where-    checkSingle tm (ValueInterface c _ n _ _ rs _) = do+    checkSingle cm (ValueInterface c _ n _ _ rs _) = do       let ts2 = map (\r -> (vrContext r,tiName $ vrType r)) rs-      is <- mapCompilerM (getCategory tm) ts2+      is <- mapCompilerM (getCategory cm) ts2       collectAllM_ (map (valueRefinesInstanceError c n) is)       collectAllM_ (map (valueRefinesConcreteError c n) is)-    checkSingle tm (ValueConcrete c _ n _ _ rs ds _ _) = do+    checkSingle cm (ValueConcrete c _ n _ _ _ rs ds _ _) = do       let ts2 = map (\r -> (vrContext r,tiName $ vrType r)) rs       let ts3 = map (\d -> (vdContext d,diName $ vdType d)) ds-      is1 <- mapCompilerM (getCategory tm) ts2-      is2 <- mapCompilerM (getCategory tm) ts3+      is1 <- mapCompilerM (getCategory cm) ts2+      is2 <- mapCompilerM (getCategory cm) ts3       collectAllM_ (map (concreteRefinesInstanceError c n) is1)       collectAllM_ (map (concreteDefinesValueError c n) is2)       collectAllM_ (map (concreteRefinesConcreteError c n) is1)@@ -637,17 +656,18 @@  checkConnectionCycles :: (Show c, CollectErrorsM m) =>   CategoryMap c -> [AnyCategory c] -> m ()-checkConnectionCycles tm0 ts = collectAllM_ (map (checker []) ts) where+checkConnectionCycles (CategoryMap km tm0) ts = collectAllM_ (map (checker []) ts) where   tm = Map.union tm0 $ Map.fromList $ zip (map getCategoryName ts) ts+  cm = CategoryMap km tm   checker us (ValueInterface c _ n _ _ rs _) = do     failIfCycle n c us     let ts2 = map (\r -> (vrContext r,tiName $ vrType r)) rs-    is <- mapCompilerM (getValueCategory tm) ts2+    is <- mapCompilerM (getValueCategory cm) ts2     collectAllM_ (map (checker (us ++ [n]) . snd) is)-  checker us (ValueConcrete c _ n _ _ rs _ _ _) = do+  checker us (ValueConcrete c _ n _ _ _ rs _ _ _) = do     failIfCycle n c us     let ts2 = map (\r -> (vrContext r,tiName $ vrType r)) rs-    is <- mapCompilerM (getValueCategory tm) ts2+    is <- mapCompilerM (getValueCategory cm) ts2     collectAllM_ (map (checker (us ++ [n]) . snd) is)   checker _ _ = return ()   failIfCycle n c us =@@ -658,9 +678,9 @@  checkParamVariances :: (Show c, CollectErrorsM m) =>   CategoryMap c -> [AnyCategory c] -> m ()-checkParamVariances tm0 ts = do-  tm <- declareAllTypes tm0 ts-  let r = CategoryResolver tm+checkParamVariances cm0 ts = do+  cm <- declareAllTypes cm0 ts+  let r = CategoryResolver cm   mapCompilerM_ (checkCategory r) ts   mapCompilerM_ checkBounds ts   where@@ -671,11 +691,12 @@       noDuplicates c n ps       let vm = Map.fromList $ map (\p -> (vpParam p,vpVariance p)) ps       collectAllM_ (map (checkRefine r vm) rs)-    checkCategory r t@(ValueConcrete c _ n _ ps rs ds _ _) = categoryContext t ??> do+    checkCategory r t@(ValueConcrete c _ n _ fv ps rs ds _ _) = categoryContext t ??> do       noDuplicates c n ps       let vm = Map.fromList $ map (\p -> (vpParam p,vpVariance p)) ps       collectAllM_ (map (checkRefine r vm) rs)       collectAllM_ (map (checkDefine r vm) ds)+      collectAllM_ (map (checkVisibility r vm) fv)     checkCategory _ t@(InstanceInterface c _ n _ ps _) = categoryContext t ??> do       noDuplicates c n ps     noDuplicates c n ps = collectAllM_ (map checkCount $ group $ sort $ map vpParam ps) where@@ -689,21 +710,35 @@     checkDefine r vm (ValueDefine c t) =       validateDefinesVariance r vm Covariant t <??         "In " ++ show t ++ formatFullContextBrace c+    checkVisibility _ _ FunctionVisibilityDefault = return ()+    checkVisibility r vm (FunctionVisibility _ ts2) =+      collectAllM_ (map (checkVisibilitySingle r vm) ts2)+    checkVisibilitySingle r vm (c,t) =+      validateInstanceVariance r vm Covariant t <??+        "In visibility " ++ show t ++ formatFullContextBrace c  checkCategoryInstances :: (Show c, CollectErrorsM m) =>   CategoryMap c -> [AnyCategory c] -> m ()-checkCategoryInstances tm0 ts = do-  tm <- declareAllTypes tm0 ts-  let r = CategoryResolver tm+checkCategoryInstances cm0 ts = do+  cm <- declareAllTypes cm0 ts+  let r = CategoryResolver cm   mapCompilerM_ (checkSingle r) ts   where     checkSingle r t = do       pa <- getCategoryParamSet t-      mapCompilerM_ (checkFilterParam pa) (getCategoryFilters t)-      mapCompilerM_ (checkRefine r pa)    (getCategoryRefines t)-      mapCompilerM_ (checkDefine r pa)    (getCategoryDefines t)-      mapCompilerM_ (checkFilter r pa)    (getCategoryFilters t)+      mapCompilerM_ (checkFilterParam pa)  (getCategoryFilters t)+      mapCompilerM_ (checkRefine r pa)     (getCategoryRefines t)+      mapCompilerM_ (checkDefine r pa)     (getCategoryDefines t)+      mapCompilerM_ (checkFilter r pa)     (getCategoryFilters t)+      mapCompilerM_ (checkVisibility r pa) (getCategoryVisibilities t)       mapCompilerM_ (validateCategoryFunction r t) (getCategoryFunctions t)+    checkVisibility r fm (FunctionVisibility c ts2) =+      mapCompilerM_ (checkVisibilitySingle r fm) ts2 <??+        "In visibility at " ++ formatFullContext c+    checkVisibility _ _ _ = return ()+    checkVisibilitySingle r fm (c,t) =+      validateGeneralInstance r fm t <??+        "In " ++ show t ++ formatFullContextBrace c     checkFilterParam pa (ParamFilter c n _) =       when (not $ n `Set.member` pa) $         compilerErrorM $ "Param " ++ show n ++ formatFullContextBrace c ++ " not found"@@ -729,7 +764,11 @@          TypeScope     -> validatateFunctionType r pa vm funcType          ValueScope    -> validatateFunctionType r pa vm funcType          _             -> return ()-    getFunctionFilterMap f >>= disallowBoundedParams where+    getFunctionFilterMap f >>= disallowBoundedParams+    checkVis (sfScope f) (sfVisibility f) where+      checkVis CategoryScope va@(FunctionVisibility _ _) =+        compilerErrorM $ "Category functions must not have restricted visibility: " ++ show va+      checkVis _ _ = return ()       message         | getCategoryName t == sfType f = "In function:\n---\n" ++ show f ++ "\n---\n"         | otherwise = "In function inherited from " ++ show (sfType f) ++@@ -737,18 +776,18 @@  topoSortCategories :: (Show c, CollectErrorsM m) =>   CategoryMap c -> [AnyCategory c] -> m [AnyCategory c]-topoSortCategories tm0 ts = do-  tm <- declareAllTypes tm0 ts-  fmap fst $ update tm (Map.keysSet tm0) ts+topoSortCategories cm0 ts = do+  cm <- declareAllTypes cm0 ts+  fmap fst $ update cm (Map.keysSet $ cmAvailable cm0) ts   where-    update tm ta (t:ts2) = do+    update cm ta (t:ts2) = do       if getCategoryName t `Set.member` ta-         then update tm ta ts2+         then update cm ta ts2          else do-           refines <- mapCompilerM (\r -> getCategory tm (vrContext r,tiName $ vrType r)) $ getCategoryRefines t-           defines <- mapCompilerM (\d -> getCategory tm (vdContext d,diName $ vdType d)) $ getCategoryDefines t-           (ts3,ta2) <- update tm (getCategoryName t `Set.insert` ta) (map snd $ refines ++ defines)-           (ts4,ta3) <- update tm ta2 ts2+           refines <- mapCompilerM (\r -> getCategory cm (vrContext r,tiName $ vrType r)) $ getCategoryRefines t+           defines <- mapCompilerM (\d -> getCategory cm (vdContext d,diName $ vdType d)) $ getCategoryDefines t+           (ts3,ta2) <- update cm (getCategoryName t `Set.insert` ta) (map snd $ refines ++ defines)+           (ts4,ta3) <- update cm ta2 ts2            return (ts3 ++ [t] ++ ts4,ta3)     update _ ta _ = return ([],ta) @@ -794,10 +833,10 @@  flattenAllConnections :: (Show c, CollectErrorsM m) =>   CategoryMap c -> [AnyCategory c] -> m [AnyCategory c]-flattenAllConnections tm0 ts = do+flattenAllConnections (CategoryMap km tm0) ts = do   -- We need to process all refines before type-checking can be done.   tm1 <- foldr preMerge (return tm0) (reverse ts)-  let r = CategoryResolver tm1+  let r = CategoryResolver (CategoryMap km tm1)   (ts',_) <- foldr (update r) (return ([],tm0)) (reverse ts)   return ts'   where@@ -808,9 +847,9 @@     preMergeSingle tm (ValueInterface c ns n pg ps rs fs) = do       rs' <- fmap concat $ mapCompilerM (getRefines tm) rs       return $ ValueInterface c ns n pg ps rs' fs-    preMergeSingle tm (ValueConcrete c ns n pg ps rs ds vs fs) = do+    preMergeSingle tm (ValueConcrete c ns n pg fv ps rs ds vs fs) = do       rs' <- fmap concat $ mapCompilerM (getRefines tm) rs-      return $ ValueConcrete c ns n pg ps rs' ds vs fs+      return $ ValueConcrete c ns n pg fv ps rs' ds vs fs     preMergeSingle _ t = return t     update r t u = do       (ts2,tm) <- u@@ -827,10 +866,10 @@       checkMerged r fm rs rs''       pg2 <- fmap concat $ mapCompilerM (getRefinesPragmas tm) rs       -- Only merge from direct parents.-      fs' <- mergeFunctions r tm pm fm rs [] fs+      fs' <- mergeFunctions r (CategoryMap km tm) pm fm rs [] fs       return $ ValueInterface c ns n (pg++pg2) ps rs'' fs'     -- TODO: Remove duplication below and/or have separate tests.-    updateSingle r tm t@(ValueConcrete c ns n pg ps rs ds vs fs) = do+    updateSingle r tm t@(ValueConcrete c ns n pg fv ps rs ds vs fs) = do       fm <- getCategoryFilterMap t       let pm = getCategoryParamMap t       rs' <- fmap concat $ mapCompilerM (getRefines tm) rs@@ -842,11 +881,11 @@       pg2 <- fmap concat $ mapCompilerM (getRefinesPragmas tm) rs       pg3 <- fmap concat $ mapCompilerM (getDefinesPragmas tm) ds       -- Only merge from direct parents.-      fs' <- mergeFunctions r tm pm fm rs ds fs-      return $ ValueConcrete c ns n (pg++pg2++pg3) ps rs'' ds' vs fs'+      fs' <- mergeFunctions r (CategoryMap km tm) pm fm rs ds fs+      return $ ValueConcrete c ns n (pg++pg2++pg3) fv ps rs'' ds' vs fs'     updateSingle _ _ t = return t     getRefines tm ra@(ValueRefine c t@(TypeInstance n _)) = do-      (_,v) <- getValueCategory tm (c,n)+      (_,v) <- getValueCategory (CategoryMap km tm) (c,n)       let refines = getCategoryRefines v       pa <- assignParams tm c t       fmap (ra:) $ mapCompilerM (subAll c pa) refines@@ -854,7 +893,7 @@       t2 <- uncheckedSubSingle (getValueForParam pa) t1       return $ ValueRefine (c ++ c1) t2     assignParams tm c (TypeInstance n ps) = do-      (_,v) <- getValueCategory tm (c,n)+      (_,v) <- getValueCategory (CategoryMap km tm) (c,n)       let ns = map vpParam $ getCategoryParams v       paired <- processPairs alwaysPair (Positional ns) ps       return $ Map.insert ParamSelf selfType $ Map.fromList paired@@ -869,31 +908,31 @@       return ()     checkConvert _ _ _ _ = return ()     getRefinesPragmas tm rf = do-      (_,t) <- getCategory tm (vrContext rf,tiName $ vrType rf)+      (_,t) <- getCategory (CategoryMap km tm) (vrContext rf,tiName $ vrType rf)       return $ map (prependCategoryPragmaContext $ vrContext rf) $ getCategoryPragmas t     getDefinesPragmas tm df = do-      (_,t) <- getCategory tm (vdContext df,diName $ vdType df)+      (_,t) <- getCategory (CategoryMap km tm) (vdContext df,diName $ vdType df)       return $ map (prependCategoryPragmaContext $ vdContext df) $ getCategoryPragmas t  mergeFunctions :: (Show c, CollectErrorsM m, TypeResolver r) =>   r -> CategoryMap c -> ParamValues -> ParamFilters -> [ValueRefine c] ->   [ValueDefine c] -> [ScopedFunction c] -> m [ScopedFunction c]-mergeFunctions r tm pm fm rs ds fs = do-  inheritValue <- fmap concat $ mapCompilerM (getRefinesFuncs tm) rs-  inheritType  <- fmap concat $ mapCompilerM (getDefinesFuncs tm) ds+mergeFunctions r cm pm fm rs ds fs = do+  inheritValue <- fmap concat $ mapCompilerM getRefinesFuncs rs+  inheritType  <- fmap concat $ mapCompilerM getDefinesFuncs ds   let inheritByName  = fmap (nubBy sameFunction) $ Map.fromListWith (++) $ map (\f -> (sfName f,[f])) $ inheritValue ++ inheritType   let explicitByName = Map.fromListWith (++) $ map (\f -> (sfName f,[f])) fs   let allNames = Set.toList $ Set.union (Map.keysSet inheritByName) (Map.keysSet explicitByName)   mapCompilerM (mergeByName inheritByName explicitByName) allNames where-    getRefinesFuncs tm2 (ValueRefine c (TypeInstance n ts2)) = do-      (_,t) <- getValueCategory tm2 (c,n)+    getRefinesFuncs (ValueRefine c (TypeInstance n ts2)) = do+      (_,t) <- getValueCategory cm (c,n)       let ps = map vpParam $ getCategoryParams t       let fs2 = getCategoryFunctions t       paired <- processPairs alwaysPair (Positional ps) ts2       let assigned = Map.fromList $ (ParamSelf,selfType):paired       mapCompilerM (unfixedSubFunction assigned) fs2-    getDefinesFuncs tm2 (ValueDefine c (DefinesInstance n ts2)) = do-      (_,t) <- getInstanceCategory tm2 (c,n)+    getDefinesFuncs (ValueDefine c (DefinesInstance n ts2)) = do+      (_,t) <- getInstanceCategory cm (c,n)       let ps = map vpParam $ getCategoryParams t       let fs2 = getCategoryFunctions t       paired <- processPairs alwaysPair (Positional ps) ts2@@ -915,9 +954,9 @@                                           show (length es) ++ " times:\n---\n" ++                                           intercalate "\n---\n" (map show es)       | otherwise = do-        let ff@(ScopedFunction c n2 t s as rs2 ps fa ms) = head es+        let ff@(ScopedFunction c n2 t s v as rs2 ps fa ms) = head es         mapCompilerM_ (checkMerge ff) is-        return $ ScopedFunction c n2 t s as rs2 ps fa (ms ++ is)+        return $ ScopedFunction c n2 t s v as rs2 ps fa (ms ++ is)         where           checkMerge f1 f2             | sfScope f1 /= sfScope f2 =@@ -926,11 +965,23 @@                                show f2 ++ "\n  ->\n" ++ show f1             | otherwise =               "In function merge:\n---\n" ++ show f2 ++ "\n  ->\n" ++ show f1 ++ "\n---\n" ??> do+                checkMergeVis (sfVisibility f1) (sfVisibility f2)                 f1' <- parsedToFunctionType f1                 f2' <- parsedToFunctionType f2                 case sfScope f1 of                      CategoryScope -> checkFunctionConvert r Map.empty Map.empty f2' f1'                      _             -> checkFunctionConvert r fm pm f2' f1'+                processPairs_ checkArgNames (sfArgs f1) (sfArgs f2)+          checkMergeVis FunctionVisibilityDefault _ = return ()+          checkMergeVis v1 v2 =+            compilerErrorM $ "Cannot supersede " ++ show v2 ++ " with " ++ show v1+          checkArgNames (_,n1) (_,n2)+            | fmap calName n1 == fmap calName n2 = return ()+          checkArgNames t1 t2 =+            compilerErrorM $ "Expected arg label from " ++ showArgName t2 +++                            " to match " ++ showArgName t1+          showArgName (t',Nothing) = show t'+          showArgName (t',Just n') = show (pvType t') ++ " " ++ show n'  data FunctionName =   FunctionName {@@ -940,24 +991,52 @@   BuiltinReduce |   BuiltinRequire |   BuiltinStrong |+  BuiltinIdentify |   BuiltinTypename   deriving (Eq,Ord)  instance Show FunctionName where   show (FunctionName n) = n-  show BuiltinPresent = "present"-  show BuiltinReduce = "reduce"-  show BuiltinRequire = "require"-  show BuiltinStrong = "strong"+  show BuiltinPresent  = "present"+  show BuiltinReduce   = "reduce"+  show BuiltinRequire  = "require"+  show BuiltinStrong   = "strong"+  show BuiltinIdentify = "identify"   show BuiltinTypename = "typename" +data CallArgLabel c =+  CallArgLabel {+    calContext :: [c],+    calName ::String+  }+  deriving (Eq,Ord)++instance Show c => Show (CallArgLabel c) where+  show (CallArgLabel c n) = n ++ formatFullContextBrace c++matchesCallArgLabel :: CallArgLabel c -> String -> Bool+matchesCallArgLabel (CallArgLabel _ n1) n2 = init n1 == n2++data FunctionVisibility c =+  FunctionVisibility {+    fvContext :: [c],+    fvTypes :: [([c],GeneralInstance)]+  } |+  FunctionVisibilityDefault+  deriving (Eq)++instance Show c => Show (FunctionVisibility c) where+  show FunctionVisibilityDefault = "visibility _"+  show (FunctionVisibility c ts) = "visibility " ++ intercalate ", " (map (show . snd) ts) ++ formatFullContextBrace c+ data ScopedFunction c =   ScopedFunction {     sfContext :: [c],     sfName :: FunctionName,     sfType :: CategoryName,     sfScope :: SymbolScope,-    sfArgs :: Positional (PassedValue c),+    sfVisibility :: FunctionVisibility c,+    sfArgs :: Positional (PassedValue c, Maybe (CallArgLabel c)),     sfReturns :: Positional (PassedValue c),     sfParams :: Positional (ValueParam c),     sfFilters :: [ParamFilter c],@@ -968,17 +1047,19 @@   show f = showFunctionInContext (show (sfScope f) ++ " ") "" f  sameFunction :: ScopedFunction c -> ScopedFunction c -> Bool-sameFunction (ScopedFunction _ n1 t1 s1 _ _ _ _ _) (ScopedFunction _ n2 t2 s2 _ _ _ _ _) =+sameFunction (ScopedFunction _ n1 t1 s1 _ _ _ _ _ _) (ScopedFunction _ n2 t2 s2 _ _ _ _ _ _) =   all id [n1 == n2, t1 == t2, s1 == s2]  showFunctionInContext :: Show c => String -> String -> ScopedFunction c -> String-showFunctionInContext s indent (ScopedFunction cs n t _ as rs ps fa ms) =+showFunctionInContext s indent (ScopedFunction cs n t _ _ as rs ps fa ms) =   indent ++ s ++ "/*" ++ show t ++ "*/ " ++ show n ++   showParams (pValues ps) ++ " " ++ formatContext cs ++ "\n" ++   concat (map (\v -> indent ++ formatValue v ++ "\n") fa) ++-  indent ++ "(" ++ intercalate "," (map (show . pvType) $ pValues as) ++ ") -> " +++  indent ++ "(" ++ intercalate "," (map showArg $ pValues as) ++ ") -> " ++   "(" ++ intercalate "," (map (show . pvType) $ pValues rs) ++ ")" ++ showMerges (flatten ms)   where+    showArg (a,Nothing) = show (pvType a)+    showArg (a,Just n2) = show (pvType a) ++ " " ++ show (calName n2)     showParams [] = ""     showParams ps2 = "<" ++ intercalate "," (map (show . vpParam) ps2) ++ ">"     formatContext cs2 = "/*" ++ formatFullContext cs2 ++ "*/"@@ -1001,8 +1082,8 @@  parsedToFunctionType :: (Show c, CollectErrorsM m) =>   ScopedFunction c -> m FunctionType-parsedToFunctionType (ScopedFunction c n _ _ as rs ps fa _) = do-  let as' = Positional $ map pvType $ pValues as+parsedToFunctionType (ScopedFunction c n _ _ _ as rs ps fa _) = do+  let as' = Positional $ map (pvType . fst) $ pValues as   let rs' = Positional $ map pvType $ pValues rs   let ps' = Positional $ map vpParam $ pValues ps   mapCompilerM_ checkFilter fa@@ -1027,40 +1108,71 @@  unfixedSubFunction :: (Show c, CollectErrorsM m) =>   ParamValues -> ScopedFunction c -> m (ScopedFunction c)-unfixedSubFunction pa ff@(ScopedFunction c n t s as rs ps fa ms) =+unfixedSubFunction pa ff@(ScopedFunction c n t s v as rs ps fa ms) =   "In function:\n---\n" ++ show ff ++ "\n---\n" ??> do     let unresolved = Map.fromList $ map (\n2 -> (n2,singleType $ JustParamName False n2)) $ map vpParam $ pValues ps     let pa' = pa `Map.union` unresolved-    as' <- fmap Positional $ mapCompilerM (subPassed pa') $ pValues as+    as' <- fmap Positional $ mapCompilerM (subPassedNamed pa') $ pValues as     rs' <- fmap Positional $ mapCompilerM (subPassed pa') $ pValues rs     fa' <- mapCompilerM (subFilter pa') fa     ms' <- mapCompilerM (uncheckedSubFunction pa) ms-    return $ (ScopedFunction c n t s as' rs' ps fa' ms')+    v' <- subVisibility pa' v+    return $ (ScopedFunction c n t s v' as' rs' ps fa' ms')     where+      subPassedNamed pa2 (a,n2) = do+        a2 <- subPassed pa2 a+        return (a2,n2)       subPassed pa2 (PassedValue c2 t2) = do         t' <- uncheckedSubValueType (getValueForParam pa2) t2         return $ PassedValue c2 t'       subFilter pa2 (ParamFilter c2 n2 f) = do         f' <- uncheckedSubFilter (getValueForParam pa2) f         return $ ParamFilter c2 n2 f'+      subVisibility _ FunctionVisibilityDefault = return FunctionVisibilityDefault+      subVisibility pa2 (FunctionVisibility c2 ts) = do+        ts' <- mapCompilerM (subVisibilitySingle pa2) ts+        return $ FunctionVisibility c2 ts'+      subVisibilitySingle pa2 (c2,t2) = do+        t2' <- uncheckedSubInstance (getValueForParam pa2) t2+        return (c2,t2')  replaceSelfFunction :: (Show c, CollectErrorsM m) =>   GeneralInstance -> ScopedFunction c -> m (ScopedFunction c)-replaceSelfFunction self ff@(ScopedFunction c n t s as rs ps fa ms) =+replaceSelfFunction self ff@(ScopedFunction c n t s v as rs ps fa ms) =   "In function:\n---\n" ++ show ff ++ "\n---\n" ??> do-    as' <- fmap Positional $ mapCompilerM subPassed $ pValues as+    as' <- fmap Positional $ mapCompilerM subPassedNamed $ pValues as     rs' <- fmap Positional $ mapCompilerM subPassed $ pValues rs     fa' <- mapCompilerM subFilter fa     ms' <- mapCompilerM (replaceSelfFunction self) ms-    return $ (ScopedFunction c n t s as' rs' ps fa' ms')+    v' <- subVisibility v+    return $ (ScopedFunction c n t s v' as' rs' ps fa' ms')     where+      subPassedNamed (a,n2) = do+        a2 <- subPassed a+        return (a2,n2)       subPassed (PassedValue c2 t2) = do         t' <- replaceSelfValueType self t2         return $ PassedValue c2 t'       subFilter (ParamFilter c2 n2 f) = do         f' <- replaceSelfFilter self f         return $ ParamFilter c2 n2 f'+      subVisibility FunctionVisibilityDefault = return FunctionVisibilityDefault+      subVisibility (FunctionVisibility c2 ts) = do+        ts' <- mapCompilerM subVisibilitySingle ts+        return $ FunctionVisibility c2 ts'+      subVisibilitySingle (c2,t2) = do+        t2' <- replaceSelfInstance self t2+        return (c2,t2') +checkFunctionCallVisibility :: (Show c, CollectErrorsM m, TypeResolver r) =>+  r -> ParamFilters -> ScopedFunction c -> GeneralInstance -> m ()+checkFunctionCallVisibility r fs f = check (sfVisibility f) where+  check FunctionVisibilityDefault _ = return ()+  check (FunctionVisibility _ ts) t0 = "Cannot call " ++ show (sfName f) ++ " in context of " ++ show t0 !!>+    collectFirstM_ (map (checkSingle t0) ts)+  checkSingle t0 (c,t) = "In visibility " ++ show t ++ formatFullContextBrace c ??>+    checkGeneralMatch r fs Covariant t0 t+ data PatternMatch =   TypePattern {     tpVariance :: Variance,@@ -1098,10 +1210,10 @@   deriving (Eq,Ord)  instance Show a => Show (GuessRange a) where-  show (GuessRange Nothing   Nothing)   = "Literally anything is possible"-  show (GuessRange Nothing   (Just hi)) = "Something at or below " ++ show hi-  show (GuessRange (Just lo) Nothing)   = "Something at or above " ++ show lo-  show (GuessRange (Just lo) (Just hi)) = "Something between " ++ show lo ++ " and " ++ show hi+  show (GuessRange Nothing   Nothing)   = "literally anything is possible"+  show (GuessRange Nothing   (Just hi)) = "something at or below " ++ show hi+  show (GuessRange (Just lo) Nothing)   = "something at or above " ++ show lo+  show (GuessRange (Just lo) (Just hi)) = "something between " ++ show lo ++ " and " ++ show hi  data GuessUnion =   GuessUnion {@@ -1130,6 +1242,7 @@  mergeInferredTypes :: (CollectErrorsM m, TypeResolver r) =>   r -> ParamFilters -> ParamFilters -> ParamValues -> MergeTree InferredTypeGuess -> m ParamValues+mergeInferredTypes _ _ ff _ _ | null (Map.toList ff) = return Map.empty mergeInferredTypes r f ff ps gs0 = do   let gs0' = mapTypeGuesses gs0   gs1 <- mapCompilerM (\(i,is) -> fmap ((,) i) $ (reduce >=> simplifyUnion) is) $ Map.toList gs0'@@ -1199,7 +1312,7 @@            _                 -> tryRangeUnion (ms ++ [g2]) g1 gs     tryRangeUnion _ _ _ = return Nothing     takeBest [gs] = return $ Map.fromList gs-    takeBest [] = compilerErrorM "No feasible param guesses found"+    takeBest [] = compilerErrorM genericError     takeBest gs = "Unable to merge alternative param guesses" !!> do       mapCompilerM_ showAmbiguous (zip ([1..] :: [Int]) gs)       emptyErrorM@@ -1209,12 +1322,14 @@       gs' <- mapCompilerM extractGuesses gs       let mult = foldM (\xs ys -> [xs++[y] | y <- ys]) [] gs'       let gs2 = map filterGuess mult-      collectFirstM_ gs2 <!! "No feasible param guesses found"+      collectFirstM_ gs2 <!! genericError       collectAnyM gs2+    genericError = "No guesses available for params " ++ intercalate ", " (map show $ Map.keys ff)     filterGuess gs = checkSubFilters gs >> return gs     extractGuesses (i,is) = do       let is2 = map (extractSingle i) is-      collectFirstM_ is2 <!! "No feasible guesses for param " ++ show i+      -- resetBackgroundM prevents duplicate messages.+      resetBackgroundM $ collectFirstM_ is2 <!! "No feasible guesses for param " ++ show i       fmap nub $ collectAnyM is2     extractSingle i (GuessRange (Just lo) Nothing) = return (i,lo)     extractSingle i (GuessRange Nothing (Just hi)) = return (i,hi)@@ -1222,7 +1337,10 @@       p <- (Just hi) `convertsTo` (Just lo)       if p          then return (i,lo)-         else compilerErrorM $ "Ambiguous guess for param " ++ show i ++ ": " ++ show g+         else do+           compilerBackgroundM $ "Arbitrarily using lower bound " ++ show lo +++                                 " for " ++ show i ++ " (" ++ show g ++ ")"+           return (i,lo)     extractSingle i g@(GuessRange Nothing Nothing) =       compilerErrorM $ "Ambiguous guess for param " ++ show i ++ ": " ++ show g     checkSubFilters gs = "In validation of inference guess: " ++ describeGuess gs ??> do
src/Types/TypeInstance.hs view
@@ -1,5 +1,5 @@ {- ------------------------------------------------------------------------------Copyright 2019-2022 Kevin P. Barry+Copyright 2019-2022,2023 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.@@ -52,6 +52,7 @@   getValueForParam,   hasInferredParams,   isDefinesFilter,+  isOptionalValue,   isRequiresFilter,   isWeakValue,   mapTypeGuesses,@@ -124,6 +125,9 @@ isWeakValue :: ValueType -> Bool isWeakValue = (== WeakValue) . vtRequired +isOptionalValue :: ValueType -> Bool+isOptionalValue = (== OptionalValue) . vtRequired+ requiredSingleton :: CategoryName -> ValueType requiredSingleton n = ValueType RequiredValue $ singleType $ JustTypeInstance $ TypeInstance n (Positional []) @@ -141,22 +145,26 @@   BuiltinFloat |   BuiltinString |   BuiltinPointer |+  BuiltinIdentifier |   BuiltinFormatted |   BuiltinOrder |+  BuiltinTestcase |   CategoryNone  instance Show CategoryName where-  show (CategoryName n)    = n-  show BuiltinBool         = "Bool"-  show BuiltinChar         = "Char"-  show BuiltinCharBuffer   = "CharBuffer"-  show BuiltinInt          = "Int"-  show BuiltinFloat        = "Float"-  show BuiltinString       = "String"-  show BuiltinPointer      = "Pointer"-  show BuiltinFormatted    = "Formatted"-  show BuiltinOrder        = "Order"-  show CategoryNone        = "(none)"+  show (CategoryName n)  = n+  show BuiltinBool       = "Bool"+  show BuiltinChar       = "Char"+  show BuiltinCharBuffer = "CharBuffer"+  show BuiltinInt        = "Int"+  show BuiltinFloat      = "Float"+  show BuiltinString     = "String"+  show BuiltinPointer    = "Pointer"+  show BuiltinIdentifier = "Identifier"+  show BuiltinFormatted  = "Formatted"+  show BuiltinOrder      = "Order"+  show BuiltinTestcase   = "Testcase"+  show CategoryNone      = "(none)"  instance Eq CategoryName where   c1 == c2 = show c1 == show c2
tests/.zeolite-module view
@@ -32,7 +32,6 @@   } ] private_deps: [-  "lib/testing"   "visibility"   "visibility2" ]@@ -51,4 +50,4 @@     defines: [Default]   } ]-mode: incremental {}+mode: incremental { }
+ tests/arg-labels.0rt view
@@ -0,0 +1,308 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "call with arg labels" {+  success+  exclude compiler "value:"+}++unittest categoryCall {+  \ Testing.checkEquals(Value:call(value: 1), 1)+}++unittest typeValueCall {+  \ Testing.checkEquals(Value.new(value: 1).add(value: 10), 11)+}++concrete Value {+  @category call (Int value:) -> (Int)+  @type new (Int value:) -> (#self)+  @value add (Int value:) -> (Int)+}++define Value {+  @value Int storedValue++  call (value) { return value }+  new (value) { return Value{ value } }+  add (value) { return storedValue+value }+}+++testcase "call with missing required label" {+  error+  require compiler "value:"+}++unittest test {+  \ Value:call(1)+}++concrete Value {+  @category call (Int value:) -> (Int)+}++define Value {+  call (value) { return value }+}+++testcase "call with unexpected label" {+  error+  require compiler "value:"+}++unittest test {+  \ Value:call(value: 1)+}++concrete Value {+  @category call (Int) -> (Int)+}++define Value {+  call (value) { return value }+}+++testcase "call with mismatched label" {+  error+  require compiler "value:"+  require compiler "number:"+}++unittest test {+  \ Value:call(number: 1)+}++concrete Value {+  @category call (Int value:) -> (Int)+}++define Value {+  call (value) { return value }+}+++testcase "merge with matched label" {+  success+}++unittest test {+  \ Testing.checkEquals(Value.call(value: 1), 1)+}++@type interface Base {+  call (Int value:) -> (Int)+}++concrete Value {+  defines Base++  @type call (Int value:) -> (Int)+}++define Value {+  call (value) { return value }+}+++testcase "failed merge with mismatched label" {+  error+  require compiler "value:"+  require compiler "number:"+}++@type interface Base {+  call (Int value:) -> (Int)+}++concrete Value {+  defines Base++  @type call (Int number:) -> (Int)+}++define Value {+  call (number) { return number }+}+++testcase "failed merge with added label" {+  error+  require compiler "number:"+}++@type interface Base {+  call (Int) -> (Int)+}++concrete Value {+  defines Base++  @type call (Int number:) -> (Int)+}++define Value {+  call (number) { return number }+}+++testcase "failed merge with removed label" {+  error+  require compiler "number:"+}++@type interface Base {+  call (Int number:) -> (Int)+}++concrete Value {+  defines Base++  @type call (Int) -> (Int)+}++define Value {+  call (number) { return number }+}+++testcase "warning when arg name differs from arg label" {+  compiles+  require compiler "value:"+  require compiler "number"+}++concrete Value {+  @type call (Int value:) -> (Int)+}++define Value {+  call (number) { return number }+}+++testcase "no warning when arg with label is ignored" {+  compiles+  exclude compiler "value:"+}++concrete Value {+  @type call (Int value:) -> (Int)+}++define Value {+  call (_) { return 1 }+}+++testcase "prefix not allowed with required labels" {+  error+  require compiler "value:"+}++unittest test {+  \ `Value.call` 123+}++concrete Value {+  @type call (Int value:) -> (Int)+}++define Value {+  call (_) { return 1 }+}+++testcase "infix not allowed with required labels" {+  error+  require compiler "value1:"+  require compiler "value2:"+}++unittest test {+  \ 987 `Value.call` 123+}++concrete Value {+  @type call (Int value1:, Int value2:) -> (Int)+}++define Value {+  call (_, _) { return 1 }+}+++testcase "arg labels disallowed when forwarding multiple args" {+  error+  require compiler "value1:"+  exclude compiler "value2:"+}++unittest test {+  \ Value.call2(value1: Value.call1())+}++concrete Value {+  @type call1 () -> (Int, Int)+  @type call2 (Int value1:, Int value2:) -> ()+}++define Value {+  call1 () { return 1, 2 }+  call2 (_, _) { }+}+++testcase "arg labels still checked when passing multiple returns" {+  error+  require compiler "value1:"+  require compiler "value2:"+}++unittest test {+  \ Value.call2(Value.call1())+}++concrete Value {+  @type call1 () -> (Int, Int)+  @type call2 (Int value1:, Int value2:) -> ()+}++define Value {+  call1 () { return 1, 2 }+  call2 (_, _) { }+}+++testcase "reusing label is allowed" {+  success+}++unittest test {+  \ Testing.checkEquals(Value.call(positive: 1, positive: 2), 3)+}++concrete Value {+  @type call (Int positive:, Int positive:) -> (Int)+}++define Value {+  call (value1, value2) { return value1+value2 }+}
tests/bad-path/.zeolite-module view
@@ -1,2 +1,2 @@ path: "/dev/null"-mode: incremental {}+mode: incremental { }
tests/builtin-types.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2020-2021 Kevin P. Barry+Copyright 2020-2021,2023 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.@@ -32,37 +32,37 @@ }  unittest bool {-  if (!present(reduce<Bool,Bool>(true))) {+  if (!present(reduce<Bool, Bool>(true))) {     fail("Failed")   } }  unittest asBool {-  if (!present(reduce<Bool,AsBool>(true))) {+  if (!present(reduce<Bool, AsBool>(true))) {     fail("Failed")   } }  unittest asChar {-  if (present(reduce<Bool,AsChar>(true))) {+  if (present(reduce<Bool, AsChar>(true))) {     fail("Failed")   } }  unittest asInt {-  if (!present(reduce<Bool,AsInt>(true))) {+  if (!present(reduce<Bool, AsInt>(true))) {     fail("Failed")   } }  unittest asFloat {-  if (!present(reduce<Bool,AsFloat>(true))) {+  if (!present(reduce<Bool, AsFloat>(true))) {     fail("Failed")   } }  unittest formatted {-  if (!present(reduce<Bool,Formatted>(true))) {+  if (!present(reduce<Bool, Formatted>(true))) {     fail("Failed")   } }@@ -73,37 +73,37 @@ }  unittest char {-  if (!present(reduce<Char,Char>('a'))) {+  if (!present(reduce<Char, Char>('a'))) {     fail("Failed")   } }  unittest asBool {-  if (!present(reduce<Char,AsBool>('a'))) {+  if (!present(reduce<Char, AsBool>('a'))) {     fail("Failed")   } }  unittest asChar {-  if (!present(reduce<Char,AsChar>('a'))) {+  if (!present(reduce<Char, AsChar>('a'))) {     fail("Failed")   } }  unittest asInt {-  if (!present(reduce<Char,AsInt>('a'))) {+  if (!present(reduce<Char, AsInt>('a'))) {     fail("Failed")   } }  unittest asFloat {-  if (!present(reduce<Char,AsFloat>('a'))) {+  if (!present(reduce<Char, AsFloat>('a'))) {     fail("Failed")   } }  unittest formatted {-  if (!present(reduce<Char,Formatted>('a'))) {+  if (!present(reduce<Char, Formatted>('a'))) {     fail("Failed")   } }@@ -114,37 +114,37 @@ }  unittest int {-  if (!present(reduce<Int,Int>(1))) {+  if (!present(reduce<Int, Int>(1))) {     fail("Failed")   } }  unittest asBool {-  if (!present(reduce<Int,AsBool>(1))) {+  if (!present(reduce<Int, AsBool>(1))) {     fail("Failed")   } }  unittest asChar {-  if (!present(reduce<Int,AsChar>(1))) {+  if (!present(reduce<Int, AsChar>(1))) {     fail("Failed")   } }  unittest asInt {-  if (!present(reduce<Int,AsInt>(1))) {+  if (!present(reduce<Int, AsInt>(1))) {     fail("Failed")   } }  unittest asFloat {-  if (!present(reduce<Int,AsFloat>(1))) {+  if (!present(reduce<Int, AsFloat>(1))) {     fail("Failed")   } }  unittest formatted {-  if (!present(reduce<Int,Formatted>(1))) {+  if (!present(reduce<Int, Formatted>(1))) {     fail("Failed")   } }@@ -155,37 +155,37 @@ }  unittest float {-  if (!present(reduce<Float,Float>(1.0))) {+  if (!present(reduce<Float, Float>(1.0))) {     fail("Failed")   } }  unittest asBool {-  if (!present(reduce<Float,AsBool>(1.0))) {+  if (!present(reduce<Float, AsBool>(1.0))) {     fail("Failed")   } }  unittest asChar {-  if (present(reduce<Float,AsChar>(1.0))) {+  if (present(reduce<Float, AsChar>(1.0))) {     fail("Failed")   } }  unittest asInt {-  if (!present(reduce<Float,AsInt>(1.0))) {+  if (!present(reduce<Float, AsInt>(1.0))) {     fail("Failed")   } }  unittest asFloat {-  if (!present(reduce<Float,AsFloat>(1.0))) {+  if (!present(reduce<Float, AsFloat>(1.0))) {     fail("Failed")   } }  unittest formatted {-  if (!present(reduce<Float,Formatted>(1.0))) {+  if (!present(reduce<Float, Formatted>(1.0))) {     fail("Failed")   } }@@ -196,31 +196,31 @@ }  unittest charBuffer {-  if (!present(reduce<CharBuffer,CharBuffer>(CharBuffer.new(0)))) {+  if (!present(reduce<CharBuffer, CharBuffer>(CharBuffer.new(0)))) {     fail("Failed")   } }  unittest readAt {-  if (!present(reduce<CharBuffer,ReadAt<Char>>(CharBuffer.new(0)))) {+  if (!present(reduce<CharBuffer, ReadAt<Char>>(CharBuffer.new(0)))) {     fail("Failed")   }-  if (present(reduce<CharBuffer,ReadAt<Int>>(CharBuffer.new(0)))) {+  if (present(reduce<CharBuffer, ReadAt<Int>>(CharBuffer.new(0)))) {     fail("Failed")   } }  unittest writeAt {-  if (!present(reduce<CharBuffer,WriteAt<Char>>(CharBuffer.new(0)))) {+  if (!present(reduce<CharBuffer, WriteAt<Char>>(CharBuffer.new(0)))) {     fail("Failed")   }-  if (present(reduce<CharBuffer,WriteAt<Int>>(CharBuffer.new(0)))) {+  if (present(reduce<CharBuffer, WriteAt<Int>>(CharBuffer.new(0)))) {     fail("Failed")   } }  unittest container {-  if (!present(reduce<CharBuffer,Container>(CharBuffer.new(0)))) {+  if (!present(reduce<CharBuffer, Container>(CharBuffer.new(0)))) {     fail("Failed")   } }@@ -231,67 +231,67 @@ }  unittest string {-  if (!present(reduce<String,String>("a"))) {+  if (!present(reduce<String, String>("a"))) {     fail("Failed")   } }  unittest asBool {-  if (!present(reduce<String,AsBool>("a"))) {+  if (!present(reduce<String, AsBool>("a"))) {     fail("Failed")   } }  unittest asChar {-  if (present(reduce<String,AsChar>("a"))) {+  if (present(reduce<String, AsChar>("a"))) {     fail("Failed")   } }  unittest asInt {-  if (present(reduce<String,AsInt>("a"))) {+  if (present(reduce<String, AsInt>("a"))) {     fail("Failed")   } }  unittest asFloat {-  if (present(reduce<String,AsFloat>("a"))) {+  if (present(reduce<String, AsFloat>("a"))) {     fail("Failed")   } }  unittest formatted {-  if (!present(reduce<String,Formatted>("a"))) {+  if (!present(reduce<String, Formatted>("a"))) {     fail("Failed")   } }  unittest defaultOrder {-  if (!present(reduce<String,DefaultOrder<Char>>("a"))) {+  if (!present(reduce<String, DefaultOrder<Char>>("a"))) {     fail("Failed")   }-  if (present(reduce<String,DefaultOrder<Int>>("a"))) {+  if (present(reduce<String, DefaultOrder<Int>>("a"))) {     fail("Failed")   } }  unittest subSequence {-  if (!present(reduce<String,SubSequence>("a"))) {+  if (!present(reduce<String, SubSequence>("a"))) {     fail("Failed")   } }  unittest readAt {-  if (!present(reduce<String,ReadAt<Char>>("a"))) {+  if (!present(reduce<String, ReadAt<Char>>("a"))) {     fail("Failed")   }-  if (present(reduce<String,ReadAt<Int>>("a"))) {+  if (present(reduce<String, ReadAt<Int>>("a"))) {     fail("Failed")   } }  unittest container {-  if (!present(reduce<String,Container>("a"))) {+  if (!present(reduce<String, Container>("a"))) {     fail("Failed")   } }@@ -306,19 +306,19 @@ }  unittest charDefault {-  \ Testing.checkEquals(Char.default(),'\000')+  \ Testing.checkEquals(Char.default(), '\000') }  unittest floatDefault {-  \ Testing.checkEquals(Float.default(),0.0)+  \ Testing.checkEquals(Float.default(), 0.0) }  unittest intDefault {-  \ Testing.checkEquals(Int.default(),0)+  \ Testing.checkEquals(Int.default(), 0) }  unittest stringDefault {-  \ Testing.checkEquals(String.default(),"")+  \ Testing.checkEquals(String.default(), "") }  unittest boolDuplicate {@@ -326,39 +326,39 @@ }  unittest charDuplicate {-  \ Testing.checkEquals('a'.duplicate(),'a')+  \ Testing.checkEquals('a'.duplicate(), 'a') }  unittest floatDuplicate {-  \ Testing.checkEquals((1.1).duplicate(),1.1)+  \ Testing.checkEquals((1.1).duplicate(), 1.1) }  unittest intDuplicate {-  \ Testing.checkEquals((123).duplicate(),123)+  \ Testing.checkEquals((123).duplicate(), 123) }  unittest stringDuplicate {-  \ Testing.checkEquals("string".duplicate(),"string")+  \ Testing.checkEquals("string".duplicate(), "string") }  unittest boolHashed {-  \ Testing.checkNotEquals(true.hashed(),false.hashed())+  \ Testing.checkNotEquals(true.hashed(), false.hashed()) }  unittest charHashed {-  \ Testing.checkNotEquals('a'.hashed(),'b'.hashed())+  \ Testing.checkNotEquals('a'.hashed(), 'b'.hashed()) }  unittest floatHashed {-  \ Testing.checkNotEquals((1.1).hashed(),(1.2).hashed())+  \ Testing.checkNotEquals((1.1).hashed(), (1.2).hashed()) }  unittest intHashed {-  \ Testing.checkNotEquals((123).hashed(),(124).hashed())+  \ Testing.checkNotEquals((123).hashed(), (124).hashed()) }  unittest stringHashed {-  \ Testing.checkNotEquals("string12".hashed(),"string21".hashed())+  \ Testing.checkNotEquals("string12".hashed(), "string21".hashed()) }  unittest stringLessThan {@@ -374,10 +374,10 @@ }  unittest stringBuilder {-  [Append<Formatted>&Build<String>] builder <- String.builder()-  \ Testing.checkEquals(builder.build(),"")-  \ Testing.checkEquals(builder.append("xyz").build(),"xyz")-  \ Testing.checkEquals(builder.append(123).build(),"xyz123")+  [Append<Formatted> & Build<String>] builder <- String.builder()+  \ Testing.checkEquals(builder.build(), "")+  \ Testing.checkEquals(builder.append("xyz").build(), "xyz")+  \ Testing.checkEquals(builder.append(123).build(), "xyz123") }  unittest charLessThan {@@ -534,38 +534,38 @@  unittest writeAndRead {   CharBuffer buffer <- CharBuffer.new(5)-      .writeAt(0,'a')-      .writeAt(1,'b')-      .writeAt(2,'c')-      .writeAt(3,'d')-      .writeAt(4,'e')+      .writeAt(0, 'a')+      .writeAt(1, 'b')+      .writeAt(2, 'c')+      .writeAt(3, 'd')+      .writeAt(4, 'e')       // overwriting here-      .writeAt(1,'B')-      .writeAt(2,'C')+      .writeAt(1, 'B')+      .writeAt(2, 'C') -  \ Testing.checkEquals(buffer.size(),5)-  \ Testing.checkEquals(buffer.readAt(0),'a')-  \ Testing.checkEquals(buffer.readAt(1),'B')-  \ Testing.checkEquals(buffer.readAt(2),'C')-  \ Testing.checkEquals(buffer.readAt(3),'d')-  \ Testing.checkEquals(buffer.readAt(4),'e')+  \ Testing.checkEquals(buffer.size(), 5)+  \ Testing.checkEquals(buffer.readAt(0), 'a')+  \ Testing.checkEquals(buffer.readAt(1), 'B')+  \ Testing.checkEquals(buffer.readAt(2), 'C')+  \ Testing.checkEquals(buffer.readAt(3), 'd')+  \ Testing.checkEquals(buffer.readAt(4), 'e') }  unittest resizeDown {-  CharBuffer buffer <- CharBuffer.new(5).resize(3).writeAt(2,'a')-  \ Testing.checkEquals(buffer.size(),3)-  \ Testing.checkEquals(buffer.readAt(2),'a')+  CharBuffer buffer <- CharBuffer.new(5).resize(3).writeAt(2, 'a')+  \ Testing.checkEquals(buffer.size(), 3)+  \ Testing.checkEquals(buffer.readAt(2), 'a') }  unittest resizeUp {-  CharBuffer buffer <- CharBuffer.new(5).resize(7).writeAt(6,'a')-  \ Testing.checkEquals(buffer.size(),7)-  \ Testing.checkEquals(buffer.readAt(6),'a')+  CharBuffer buffer <- CharBuffer.new(5).resize(7).writeAt(6, 'a')+  \ Testing.checkEquals(buffer.size(), 7)+  \ Testing.checkEquals(buffer.readAt(6), 'a') }   testcase "CharBuffer read negative" {-  crash+  failure   require "-10"   require "bounds" }@@ -576,7 +576,7 @@   testcase "CharBuffer read past end" {-  crash+  failure   require "3"   require "bounds" }@@ -587,29 +587,29 @@   testcase "CharBuffer write negative" {-  crash+  failure   require "-10"   require "bounds" }  unittest test {-  \ CharBuffer.new(3).writeAt(-10,'a')+  \ CharBuffer.new(3).writeAt(-10, 'a') }   testcase "CharBuffer write past end" {-  crash+  failure   require "3"   require "bounds" }  unittest test {-  \ CharBuffer.new(3).writeAt(3,'a')+  \ CharBuffer.new(3).writeAt(3, 'a') }   testcase "CharBuffer new negative" {-  crash+  failure   require "-10"   require "size" }@@ -620,7 +620,7 @@   testcase "CharBuffer resize negative" {-  crash+  failure   require "-10"   require "size" }@@ -640,7 +640,7 @@   if (!present(strong(value2))) {     fail("Failed")   }-  [Append<Formatted>&Build<String>] builder <- String.builder().append(require(value1))+  [Append<Formatted> & Build<String>] builder <- String.builder().append(require(value1))   value1 <- empty   if (present(strong(value2))) {     fail("Failed")@@ -661,7 +661,7 @@  unittest subsequence {   String s <- "abcde"-  String s2 <- s.subSequence(1,3)+  String s2 <- s.subSequence(1, 3)   if (s2 != "bcd") {     fail(s2)   }@@ -669,7 +669,7 @@  unittest emptySubsequence {   String s <- ""-  String s2 <- s.subSequence(0,0)+  String s2 <- s.subSequence(0, 0)   if (s2 != "") {     fail(s2)   }@@ -689,26 +689,26 @@   String value <- "abcdefg"    traverse (value.defaultOrder() -> Char c) {-    \ Testing.checkEquals(c,value.readAt(index))+    \ Testing.checkEquals(c, value.readAt(index))     index <- index+1   } -  \ Testing.checkEquals(index,7)+  \ Testing.checkEquals(index, 7) }  unittest fromCharBuffer {   CharBuffer buffer <- CharBuffer.new(5)-      .writeAt(0,'a')-      .writeAt(1,'b')-      .writeAt(2,'c')-      .writeAt(3,'d')-      .writeAt(4,'e')-  \ Testing.checkEquals(String.fromCharBuffer(buffer),"abcde")+      .writeAt(0, 'a')+      .writeAt(1, 'b')+      .writeAt(2, 'c')+      .writeAt(3, 'd')+      .writeAt(4, 'e')+  \ Testing.checkEquals(String.fromCharBuffer(buffer), "abcde") }   testcase "String access negative" {-  crash+  failure   require "-10"   require "bounds" }@@ -729,7 +729,7 @@   testcase "String access past end" {-  crash+  failure   require "3"   require "bounds" }@@ -750,7 +750,7 @@   testcase "String subsequence past end" {-  crash+  failure   require "3"   require "size" }@@ -761,7 +761,7 @@  define Test {   run () {-    \ "abc".subSequence(1,3)+    \ "abc".subSequence(1, 3)   } } @@ -775,19 +775,19 @@ }  unittest accurateMax {-  \ Testing.checkEquals(Char.maxBound().asInt(),255)+  \ Testing.checkEquals(Char.maxBound().asInt(), 255) }  unittest accurateMin {-  \ Testing.checkEquals(Char.minBound().asInt(),0)+  \ Testing.checkEquals(Char.minBound().asInt(), 0) }  unittest asIntIsUnsigned {-  \ Testing.checkEquals('\xff'.asInt(),255)+  \ Testing.checkEquals('\xff'.asInt(), 255) }  unittest asFloatIsUnsigned {-  \ Testing.checkEquals('\xff'.asFloat(),255.0)+  \ Testing.checkEquals('\xff'.asFloat(), 255.0) }  @@ -796,21 +796,21 @@ }  unittest accurateMax {-  \ Testing.checkEquals(Int.maxBound(),9223372036854775807)+  \ Testing.checkEquals(Int.maxBound(), 9223372036854775807) }  unittest accurateMin {-  \ Testing.checkEquals(Int.minBound(),-9223372036854775808)+  \ Testing.checkEquals(Int.minBound(), -9223372036854775808) }  unittest asCharIsPeriodic {-  \ Testing.checkEquals((65).asChar(),(65+256).asChar())-  \ Testing.checkEquals((65).asChar(),(65+1024).asChar())-  \ Testing.checkEquals((65).asChar(),(65-1024).asChar())+  \ Testing.checkEquals((65).asChar(), (65+256).asChar())+  \ Testing.checkEquals((65).asChar(), (65+1024).asChar())+  \ Testing.checkEquals((65).asChar(), (65-1024).asChar()) }  unittest hexUnsigned {-  \ Testing.checkEquals(\xffffffffffffffff,-1)+  \ Testing.checkEquals(\xffffffffffffffff, -1) }  @@ -1057,4 +1057,34 @@   if (b2 != true) {     fail(b2)   }+}+++testcase "Float parsing" {+  success+}++unittest decUnescaped {+  \ Testing.checkEquals(123.456e-3, 123.0/1000.0+456.0/1000.0/1000.0)+  \ Testing.checkEquals(123.456e3, 123.0*1000.0+456.0)+}++unittest decEscaped {+  \ Testing.checkEquals(\d123.456, 123.456)+  \ Testing.checkEquals(\D123.456, 123.456)+}++unittest hexEscaped {+  \ Testing.checkEquals(\xff.ee, 255.0+238.0/256.0)+  \ Testing.checkEquals(\Xff.ee, 255.0+238.0/256.0)+}++unittest octEscaped {+  \ Testing.checkEquals(\o10.10, 8.125)+  \ Testing.checkEquals(\O10.10, 8.125)+}++unittest binEscaped {+  \ Testing.checkEquals(\b101.101, 5.0+5.0/8.0)+  \ Testing.checkEquals(\B101.101, 5.0+5.0/8.0) }
tests/check-defs/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../.." path: "tests/check-defs"-mode: incremental {}+mode: incremental { }
tests/check-defs/private1.0rx view
@@ -16,4 +16,4 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -define Type {}+define Type { }
tests/check-defs/private2.0rx view
@@ -16,4 +16,4 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -define Type {}+define Type { }
tests/check-defs/public.0rp view
@@ -16,6 +16,6 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -concrete Type {}+concrete Type { } -concrete Undefined {}+concrete Undefined { }
tests/cli-tests.sh view
@@ -1,7 +1,7 @@ #!/usr/bin/env bash  # -------------------------------------------------------------------------------# Copyright 2020-2022 Kevin P. Barry+# Copyright 2020-2023 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.@@ -84,6 +84,22 @@ }  +test_custom_testcase() {+  do_zeolite -p "$ZEOLITE_PATH" $PARALLEL -r tests/custom-testcase -f+  local output=$(do_zeolite -p "$ZEOLITE_PATH" -t tests/custom-testcase 2>&1 || true)+  if ! echo "$output" | egrep -q 'Passed.+ 0 .*Failed.+ 4 .*'; then+    show_message 'Expected 4 failed tests and 0 passing:'+    echo "$output" 1>&2+    return 1+  fi+  if [[ $(echo "$output" | egrep -c 'custom testcase') -ne 4 ]]; then+    show_message 'Expected 4 test failures to be related to "custom testcase":'+    echo "$output" 1>&2+    return 1+  fi+}++ require_patterns() {   local output=$1   local error=0@@ -214,7 +230,7 @@   test_leak_check() {-  local binary="$ZEOLITE_PATH/tests/leak-check/LeakTest"+  local binary="$ZEOLITE_PATH/tests/leak-check/LeakCheck"   rm -f "$binary"   do_zeolite -p "$ZEOLITE_PATH" $PARALLEL -r tests/leak-check -f   # race-condition check@@ -304,12 +320,12 @@  test_module_only() {   local output=$(do_zeolite -p "$ZEOLITE_PATH" -R tests/module-only -f || true)-  if ! echo "$output" | egrep -q 'Type1 not found'; then+  if ! echo "$output" | egrep -q 'Type1.+not found'; then     show_message 'Expected Type1 definition error from tests/module-only:'     echo "$output" 1>&2     return 1   fi-  if echo "$output" | egrep -q 'Type2 not found'; then+  if echo "$output" | egrep -q 'Type2.+not (found|visible)'; then     show_message 'Unexpected Type2 definition error from tests/module-only:'     echo "$output" 1>&2     return 1@@ -319,12 +335,12 @@  test_module_only2() {   local output=$(do_zeolite -p "$ZEOLITE_PATH" -R tests/module-only2 -f || true)-  if ! echo "$output" | egrep -q 'Type1'; then+  if ! echo "$output" | egrep -q 'Type1.+not visible'; then     show_message 'Expected Type1 definition error from tests/module-only2:'     echo "$output" 1>&2     return 1   fi-  if echo "$output" | egrep -q 'Type2'; then+  if echo "$output" | egrep -q 'Type2.+not (found|visible)'; then     show_message 'Unexpected Type2 definition error from tests/module-only2:'     echo "$output" 1>&2     return 1@@ -567,6 +583,7 @@   test_bad_path   test_bad_system_include   test_check_defs+  test_custom_testcase   test_example_hello   test_example_parser   test_example_primes
tests/conditionals.0rt view
@@ -33,7 +33,7 @@   } } -concrete Value {}+concrete Value { }   testcase "return if/elif/else" {@@ -53,7 +53,7 @@   } } -concrete Value {}+concrete Value { }   testcase "assign if/elif condition" {@@ -71,7 +71,7 @@   } } -concrete Value {}+concrete Value { }   testcase "different in if and else" {@@ -81,8 +81,8 @@ }  define Value {-  @value process () -> (optional Value,optional Value)-  process () (value1,value2) {+  @value process () -> (optional Value, optional Value)+  process () (value1, value2) {     if (false) {       value1 <- empty     } else {@@ -91,7 +91,7 @@   } } -concrete Value {}+concrete Value { }   testcase "missing in if" {@@ -111,7 +111,7 @@   } } -concrete Value {}+concrete Value { }   testcase "missing in elif" {@@ -131,7 +131,7 @@   } } -concrete Value {}+concrete Value { }   testcase "missing in else" {@@ -152,7 +152,7 @@ }  -concrete Value {}+concrete Value { }   testcase "missing in implicit else" {@@ -171,7 +171,7 @@   } } -concrete Value {}+concrete Value { }   testcase "return set in predicate for subsequent blocks" {@@ -190,7 +190,7 @@   } } -concrete Value {}+concrete Value { }   @@ -212,14 +212,14 @@   } } -concrete Value {}+concrete Value { }   testcase "branch jump skips validation of named return" {   compiles } -concrete Test {}+concrete Test { }  define Test {   @value process () -> (Bool)@@ -239,7 +239,7 @@   testcase "crash in if" {-  crash+  failure   require "empty" } @@ -252,7 +252,7 @@   testcase "crash in elif" {-  crash+  failure   require "empty" } @@ -270,8 +270,8 @@ }  define Value {-  @value process () -> (optional Value,optional Value)-  process () (value1,value2) {+  @value process () -> (optional Value, optional Value)+  process () (value1, value2) {     if (false) {       value1 <- empty       value2 <- empty@@ -285,7 +285,7 @@   } } -concrete Value {}+concrete Value { }   testcase "multi missing in if" {@@ -294,8 +294,8 @@ }  define Value {-  @value process () -> (optional Value,optional Value)-  process () (value1,value2) {+  @value process () -> (optional Value, optional Value)+  process () (value1, value2) {     if (false) {       value1 <- empty     } elif (false) {@@ -308,7 +308,7 @@   } } -concrete Value {}+concrete Value { }   testcase "multi missing in elif" {@@ -317,8 +317,8 @@ }  define Value {-  @value process () -> (optional Value,optional Value)-  process () (value1,value2) {+  @value process () -> (optional Value, optional Value)+  process () (value1, value2) {     if (false) {       value1 <- empty       value2 <- empty@@ -331,7 +331,7 @@   } } -concrete Value {}+concrete Value { }   testcase "multi missing in else" {@@ -340,8 +340,8 @@ }  define Value {-  @value process () -> (optional Value,optional Value)-  process () (value1,value2) {+  @value process () -> (optional Value, optional Value)+  process () (value1, value2) {     if (false) {       value1 <- empty       value2 <- empty@@ -354,7 +354,7 @@   } } -concrete Value {}+concrete Value { }   testcase "cleanup before return in if" {
tests/conversions.0rt view
@@ -21,33 +21,33 @@ }  unittest toType {-  \ Testing.checkEquals(Helper.getType(Value.create()?Base1),"Base1")+  \ Testing.checkEquals(Helper.getType(Value.create()?Base1), "Base1") }  unittest toAny {-  \ Testing.checkEquals(Helper.getType(Value.create()?any),"any")+  \ Testing.checkEquals(Helper.getType(Value.create()?any), "any") }  unittest toUnion {-  \ Testing.checkEquals(Helper.getType(Value.create()?[Base1|Base2]),"[Base1|Base2]")+  \ Testing.checkEquals(Helper.getType(Value.create()?[Base1 | Base2]), "[Base1|Base2]") }  unittest toIntersect {-  \ Testing.checkEquals(Helper.getType(Value.create()?[Base1&Base2]),"[Base1&Base2]")+  \ Testing.checkEquals(Helper.getType(Value.create()?[Base1 & Base2]), "[Base1&Base2]") }  unittest toParam {-  \ Testing.checkEquals(Helper.toParam<Value,Base1>(Value.create()),"Base1")+  \ Testing.checkEquals(Helper.toParam<Value, Base1>(Value.create()), "Base1") }  unittest toTypeOptional {   optional Value value <- Value.create()-  \ Testing.checkEquals(Helper.getType2(value?Base1),"Base1")+  \ Testing.checkEquals(Helper.getType2(value?Base1), "Base1") }  unittest toAnyOptional {   optional Value value <- Value.create()-  \ Testing.checkEquals(Helper.getType2(value?any),"any")+  \ Testing.checkEquals(Helper.getType2(value?any), "any") }  unittest convertedCall {@@ -56,7 +56,7 @@ }  concrete Helper {-  @type toParam<#x,#y>+  @type toParam<#x, #y>     #x requires #y   (#x) -> (String) @@ -95,7 +95,7 @@ }  define Value {-  call () {}+  call () { }    create () {     return Value{}@@ -124,7 +124,7 @@ }  define Value {-  call () {}+  call () { }    create () {     return Value{}
+ tests/custom-testcase/.zeolite-module view
@@ -0,0 +1,3 @@+root: "../.."+path: "tests/custom-testcase"+mode: incremental { }
+ tests/custom-testcase/README.md view
@@ -0,0 +1,14 @@+# Custom `Testcase` Compiler Failures.++_All_ tests this module should **always fail**. It tests that compiling a+`testcase` with a custom `Testcase` catches type issues.++To compile and run the tests:++```shell+ZEOLITE_PATH=$(zeolite --get-path)+zeolite -p $ZEOLITE_PATH -r tests/custom-testcase+zeolite -p $ZEOLITE_PATH -t tests/custom-testcase+```++_Every_ test should fail with an error related to `custom testcase`.
+ tests/custom-testcase/tests.0rt view
@@ -0,0 +1,63 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "success with unknown type" {+  success Foo+}++unittest test { }+++testcase "success with non-Testcase type" {+  success String+}++unittest test { }+++testcase "success with param" {+  success Helper<#x>+}++concrete Helper<#x> {+  defines Testcase+}++define Helper {+  start () { }+  finish () { }+}++unittest test { }+++testcase "success with invalid substitution" {+  success Helper<CharBuffer>+}++concrete Helper<#x> {+  defines Testcase+  #x immutable+}++define Helper {+  start () { }+  finish () { }+}++unittest test { }
tests/defer.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021-2022 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.@@ -61,6 +61,34 @@ }  +testcase "defer does not unset members" {+  success+}++concrete Test {+  @type new () -> (#self)+  @value deferMembers () -> ()+  @value getValueMember () -> (String)+  @value getCategoryMember () -> (String)+}++define Test {+  @category String categoryMember <- "abc"+  @value    String valueMember++  new () { return #self{ "def" } }+  deferMembers () { categoryMember, valueMember <- defer }+  getValueMember () { return valueMember }+  getCategoryMember () { return categoryMember }+}++unittest test {+  Test test <- Test.new()+  \ Testing.checkEquals(test.getCategoryMember(), "abc")+  \ Testing.checkEquals(test.getValueMember(), "def")+}++ testcase "multiple deferred" {   error   require "value1"@@ -92,7 +120,7 @@   require "initialized" } -concrete Type {}+concrete Type { }  define Type {   @value Int value@@ -111,7 +139,7 @@   require "initialized" } -concrete Type {}+concrete Type { }  define Type {   @category Int value <- 1@@ -131,7 +159,7 @@   require "read-only" } -concrete Type {}+concrete Type { }  define Type {   @value call (Int) -> ()@@ -327,7 +355,7 @@   testcase "deferred not checked in condition that jumps" {-  crash+  failure   require "success" } 
+ tests/delegation.0rt view
@@ -0,0 +1,294 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "delegate to functions" {+  success+}++unittest fromCategory {+  \ Testing.checkEquals(Value:call1(13, "message"), 123-13+7)+}++unittest fromType {+  \ Testing.checkEquals(Value.call2(13, "message"), 456-13+7)+}++unittest fromValue {+  \ Testing.checkEquals(Value.new().call3(13, "message"), 789-13+7)+}++concrete Value {+  @type new () -> (#self)+  @category call1 (Int, String) -> (Int)+  @type call2 (Int, String) -> (Int)+  @value call3 (Int, String) -> (Int)+}++define Value {+  new () { return #self{ } }++  call1 (number1, message1) {+    return delegate -> `delegatedTo1`+  }++  call2 (number2, message2) {+    \ delegate -> `delegatedTo1`+    return delegate -> `delegatedTo2`+  }++  call3 (number3, message3) {+    \ delegate -> `delegatedTo1`+    \ delegate -> `delegatedTo2`+    return delegate -> `delegatedTo3`+  }++  @category delegatedTo1 (Int, String) -> (Int)+  delegatedTo1 (number, message) {+    return 123-number+message.size()+  }++  @type delegatedTo2 (Int, String) -> (Int)+  delegatedTo2 (number, message) {+    return 456-number+message.size()+  }++  @value delegatedTo3 (Int, String) -> (Int)+  delegatedTo3 (number, message) {+    return 789-number+message.size()+  }+}+++testcase "delegate to correct initializer" {+  success+}++unittest fromCategory {+  Value value <- Value:new1(13, "message")+  \ Testing.checkEquals(value.getInt(), 13)+  \ Testing.checkEquals(value.getString(), "message")+}++unittest fromType {+  Value value <- Value.new2(13, "message")+  \ Testing.checkEquals(value.getInt(), 13)+  \ Testing.checkEquals(value.getString(), "message")+}++unittest fromValue {+  Value value <- Value.new2(9, "error")+  value <- value.new3(13, "message")+  \ Testing.checkEquals(value.getInt(), 13)+  \ Testing.checkEquals(value.getString(), "message")+}++concrete Value {+  @category new1 (Int, String) -> (Value)+  @type new2 (Int, String) -> (Value)+  @value new3 (Int, String) -> (Value)+  @value getInt () -> (Int)+  @value getString () -> (String)+}++define Value {+  @value Int number+  @value String message++  new1 (number1, message1) {+    return delegate -> Value+  }++  new2 (number2, message2) {+    return delegate -> Value+  }++  new3 (number3, message3) {+    return delegate -> Value+  }++  getInt () { return number }+  getString () { return message }+}+++testcase "delegate to #self" {+  success+}++unittest fromType {+  Value value <- Value.new1(13, "message")+  \ Testing.checkEquals(value.getInt(), 13)+  \ Testing.checkEquals(value.getString(), "message")+}++unittest fromValue {+  Value value <- Value.new1(9, "error")+  value <- value.new2(13, "message")+  \ Testing.checkEquals(value.getInt(), 13)+  \ Testing.checkEquals(value.getString(), "message")+}++concrete Value {+  @type new1 (Int, String) -> (Value)+  @value new2 (Int, String) -> (Value)+  @value getInt () -> (Int)+  @value getString () -> (String)+}++define Value {+  @value Int number+  @value String message++  new1 (number1, message1) {+    return delegate -> #self+  }++  new2 (number2, message2) {+    return delegate -> #self+  }++  getInt () { return number }+  getString () { return message }+}+++testcase "delegate fails from unittest" {+  error+  require compiler "delegation"+}++unittest test {+  \ delegate -> `Value:new`+}++concrete Value {+  @category new () -> (Value)+}++define Value {+  new () {+    return Value{ }+  }+}+++testcase "delegate fails from @category variable initializer" {+  error+  require compiler "delegation"+}++concrete Value { }++define Value {+  @category Value value <- delegate -> Value+}+++testcase "delegate fails with ignored args" {+  error+  require compiler "ignore"+}++concrete Value {+  @category new (Int, String) -> (Value)+}++define Value {+  new (value, _) {+    return delegate -> `delegatedTo`+  }++  @category delegatedTo (Int, String) -> (Value)+  delegatedTo (number, message) {+    return Value{ }+  }+}+++testcase "delegate fails with hidden args" {+  error+  require compiler "message"+  require compiler "hidden"+}++concrete Value {+  @category new (Int, String) -> (Value)+}++define Value {+  new (value, message) {+    $Hidden[message]$+    return delegate -> `delegatedTo`+  }++  @category delegatedTo (Int, String) -> (Value)+  delegatedTo (number, message) {+    return Value{ }+  }+}+++testcase "delegate fails with missing label" {+  error+  require compiler "message:"+}++concrete Value {+  @category new (Int, String) -> (Value)+}++define Value {+  new (number, message) {+    return delegate -> `delegatedTo`+  }++  @category delegatedTo (Int, String message:) -> (Value)+  delegatedTo (number, message) {+    return Value{ }+  }+}+++testcase "delegate passes along labels" {+  success+}++unittest test {+  \ Testing.checkEquals(Value:new(13, message: "message").getString(), "message")+}++concrete Value {+  @category new (Int, String message:) -> (Value)+  @value getString () -> (String)+}++define Value {+  @value Int number+  @value String message++  new (number, message) {+    return delegate -> `delegatedTo`+  }++  getString () { return message }++  @category delegatedTo (Int, String message:) -> (Value)+  delegatedTo (number, message) {+    return delegate -> Value+  }+}
tests/expr-lookup.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2020 Kevin P. Barry+Copyright 2020,2023 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.@@ -27,7 +27,7 @@   testcase "MODULE_PATH is absolute" {-  crash+  failure   require "Failed condition: /.+/tests" } @@ -37,7 +37,7 @@   testcase "MODULE_PATH from regular source" {-  crash+  failure   require "Failed condition: /.+/tests" } @@ -57,7 +57,7 @@   testcase "macro used inline in expressions" {-  crash+  failure   require "Failed condition: /.+/tests is the path" } @@ -71,7 +71,7 @@ }  unittest test {-  \ Testing.checkEquals($ExprLookup[INT_EXPR]$,4)+  \ 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]$@@ -83,7 +83,7 @@ }  unittest test {-  \ Testing.checkEquals(ExprLookup.intExpr(),4)+  \ Testing.checkEquals(ExprLookup.intExpr(), 4) }  @@ -99,7 +99,7 @@   @category String macroLocalVar <- "hello"    run () {-    \ Testing.checkEquals($ExprLookup[LOCAL_VAR]$,"hello")+    \ Testing.checkEquals($ExprLookup[LOCAL_VAR]$, "hello")   } } @@ -124,7 +124,7 @@ }  unittest test {-  \ Testing.checkEquals(ExprLookup.localVar(),99)+  \ Testing.checkEquals(ExprLookup.localVar(), 99) }  @@ -133,7 +133,7 @@ }  unittest test {-  \ Testing.checkEquals($ExprLookup[META_VAR]$,20)+  \ Testing.checkEquals($ExprLookup[META_VAR]$, 20) }  @@ -142,17 +142,18 @@ }  unittest test {-  \ Testing.checkEquals($ExprLookup[INT_EXPR]$.formatted(),"4")+  \ Testing.checkEquals($ExprLookup[INT_EXPR]$.formatted(), "4") }   testcase "source context" {-  crash-  require "tests/expr-lookup\.0rt"+  failure+  require "Failed condition: .*tests/expr-lookup\.0rt" }  unittest test {-  fail($SourceContext$)+  Formatted context <- $SourceContext$+  fail(context) }  @@ -167,4 +168,22 @@  unittest test {   String value <- $ExprLookup[USES_RECURSIVE]$+}+++testcase "call trace" {+  failure+  require "Failed condition: .*tests/expr-lookup\.0rt .*testcase"+}++unittest test {+  optional Order<Formatted> trace <- $CallTrace$+  \ Testing.checkPresent(trace)+  \ Testing.checkPresent(trace&.next())+  String combined <- String.builder()+      .append(require(trace).get())+      .append(" ")+      .append(require(trace&.next()).get())+      .build()+  fail(combined) }
tests/extension.0rt view
@@ -21,5 +21,5 @@ }  unittest test {-  \ Testing.checkEquals(Extension.execute(),"message")+  \ Testing.checkEquals(Extension.execute(), "message") }
tests/filters.0rt view
@@ -31,7 +31,7 @@ }  define Value {-  something () {}+  something () { } }  @@ -42,13 +42,13 @@   require compiler "[Ll]ower.+ \[Type3\|Type4\]" } -@value interface Type1 {}+@value interface Type1 { } -@value interface Type2 {}+@value interface Type2 { } -@value interface Type3 {}+@value interface Type3 { } -@value interface Type4 {}+@value interface Type4 { }  concrete Value<#x> {   #x requires Type1@@ -57,7 +57,7 @@   #x allows   Type4 } -define Value {}+define Value { }   testcase "implicit bound from reversing another filter" {@@ -67,46 +67,46 @@   require compiler "[Ll]ower.+ #y" } -@value interface Type {}+@value interface Type { } -concrete Value<#x,#y> {+concrete Value<#x, #y> {   #x requires Type   #y requires #x } -define Value {}+define Value { }   testcase "defines filter is not an upper bound" {   compiles } -@type interface Type1 {}+@type interface Type1 { } -@value interface Type2 {}+@value interface Type2 { }  concrete Value<#x> {   #x defines Type1   #x allows  Type2 } -define Value {}+define Value { }   testcase "defines filter is not a lower bound" {   compiles } -@type interface Type1 {}+@type interface Type1 { } -@value interface Type2 {}+@value interface Type2 { }  concrete Value<#x> {   #x defines  Type1   #x requires Type2 } -define Value {}+define Value { }   testcase "function param bounded on both sides" {@@ -114,9 +114,9 @@   require compiler "#x.+bound" } -@value interface Type1 {}+@value interface Type1 { } -@value interface Type2 {}+@value interface Type2 { }  @value interface Value {   call<#x>@@ -138,7 +138,7 @@ }  define Type {-  call () {}+  call () { }    @category call2 () -> ()   call2 () {@@ -159,7 +159,7 @@ }  define Type {-  call () {}+  call () { }    @category call2 () -> ()   call2 () {@@ -180,7 +180,7 @@ }  define Type {-  call () {}+  call () { }    @category call2 () -> ()   call2 () {@@ -255,7 +255,7 @@ }  define Type {-  call () {}+  call () { }    @category call2 () -> ()   call2 () {@@ -276,7 +276,7 @@ }  define Type {-  call () {}+  call () { }    @category call2 () -> ()   call2 () {@@ -297,7 +297,7 @@ }  define Type {-  call () {}+  call () { }    @category call2 () -> ()   call2 () {@@ -311,7 +311,7 @@ }  concrete Type1 {-  @type call<#i,#j,#k>+  @type call<#i, #j, #k>     #i requires Formatted     #j defines Equals<#j>     #k allows Int@@ -319,10 +319,10 @@ }  define Type1 {-  call () {}+  call () { } } -concrete Type2<#x,#y,#z> {+concrete Type2<#x, #y, #z> {   #x requires Formatted   #y defines Equals<#y>   #z allows Int@@ -332,7 +332,7 @@  define Type2 {   call () {-    \ Type1.call<#x,#y,#z>()+    \ Type1.call<#x, #y, #z>()   } } @@ -347,7 +347,7 @@   #x requires String } -define Type {}+define Type { }  concrete Test {   @type call<#x>@@ -356,7 +356,7 @@ }  define Test {-  call (_) {}+  call (_) { }    @type call2 () -> ()   call2 () {@@ -370,40 +370,40 @@   compiles } -concrete Test {}+concrete Test { }  define Test {-  @category call1<#x,#y>+  @category call1<#x, #y>     #y immutable     #x defines LessThan<#x>     #x requires Formatted     #y allows Int-  (#x,#y) -> ()-  call1 (x,y) {-    \ call1<#x,#y>(x,y)+  (#x, #y) -> ()+  call1 (x, y) {+    \ call1<#x, #y>(x, y)   } -  @type call2<#x,#y>+  @type call2<#x, #y>     #y immutable     #x defines LessThan<#x>     #x requires Formatted     #y allows Int-  (#x,#y) -> ()-  call2 (x,y) {-    \ call2<#x,#y>(x,y)-    \ call1<#x,#y>(x,y)+  (#x, #y) -> ()+  call2 (x, y) {+    \ call2<#x, #y>(x, y)+    \ call1<#x, #y>(x, y)   } -  @value call3<#x,#y>+  @value call3<#x, #y>     #y immutable     #x defines LessThan<#x>     #x requires Formatted     #y allows Int-  (#x,#y) -> ()-  call3 (x,y) {-    \ call3<#x,#y>(x,y)-    \ call2<#x,#y>(x,y)-    \ call1<#x,#y>(x,y)+  (#x, #y) -> ()+  call3 (x, y) {+    \ call3<#x, #y>(x, y)+    \ call2<#x, #y>(x, y)+    \ call1<#x, #y>(x, y)   } } @@ -412,17 +412,17 @@   compiles } -concrete Test<#x,#y> {}+concrete Test<#x, #y> { }  define Test {-  @category call<#x,#y>+  @category call<#x, #y>     #y immutable     #x defines LessThan<#x>     #x requires Formatted     #y allows Int-  (#x,#y) -> ()-  call (x,y) {-    \ call<#x,#y>(x,y)+  (#x, #y) -> ()+  call (x, y) {+    \ call<#x, #y>(x, y)   } } @@ -437,7 +437,7 @@  concrete Test {   @type call<#x>-    #x allows [Formatted&AsBool]+    #x allows [Formatted & AsBool]   () -> (#x) } @@ -462,7 +462,7 @@  concrete Test {   @type call<#x>-    #x allows [Formatted&AsBool]+    #x allows [Formatted & AsBool]   () -> (#x) } @@ -483,7 +483,7 @@  concrete Test {   @type call<#x>-    #x requires [Int|String]+    #x requires [Int | String]   (#x) -> () } @@ -507,7 +507,7 @@  concrete Test {   @type call<#x>-    #x requires [Int|String]+    #x requires [Int | String]   (#x) -> () } 
tests/freshness/.zeolite-module view
@@ -4,4 +4,4 @@   "tests/freshness/sub1"   "tests/../tests/freshness/sub2" ]-mode: incremental {}+mode: incremental { }
tests/freshness/reverse/.zeolite-module view
@@ -3,4 +3,4 @@ private_deps: [   "../../../tests/freshness" ]-mode: incremental {}+mode: incremental { }
tests/function-calls.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2020-2021 Kevin P. Barry+Copyright 2020-2021,2023 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.@@ -24,7 +24,7 @@ }  unittest test {-  [Value1|Value2] value <- Value1.create()+  [Value1 | Value2] value <- Value1.create()   \ value.get() } @@ -72,7 +72,7 @@ }  unittest test {-  [Value1|Value2] value <- Value1.create()+  [Value1 | Value2] value <- Value1.create()   \ value.get() } @@ -119,7 +119,7 @@ }  unittest test {-  [Int|String] value <- 1+  [Int | String] value <- 1   \ value.asFloat() } @@ -129,8 +129,8 @@ }  unittest test {-  [Value1|Value2] value <- Value1.create()-  \ Testing.checkEquals(value.get().formatted(),"1")+  [Value1 | Value2] value <- Value1.create()+  \ Testing.checkEquals(value.get().formatted(), "1") }  @value interface Base<|#x> {@@ -177,7 +177,7 @@ }  unittest test {-  [Value1|Value2] value <- Value1.create()+  [Value1 | Value2] value <- Value1.create()   \ value.get()+1 } @@ -221,8 +221,8 @@ }  unittest test {-  [Value1|Value2] value <- Value1.create()-  \ Testing.checkEquals(value?Base<Formatted>.get().formatted(),"1")+  [Value1 | Value2] value <- Value1.create()+  \ Testing.checkEquals(value?Base<Formatted>.get().formatted(), "1") }  @value interface Base<|#x> {@@ -280,7 +280,7 @@ }  unittest test {-  [Base<AsBool>&Base<Formatted>] value <- Value1.create()+  [Base<AsBool> & Base<Formatted>] value <- Value1.create()   \ value.get() } @@ -326,7 +326,7 @@ }  unittest test {-  [AsBool&Formatted] value <- 1+  [AsBool & Formatted] value <- 1   \ value.asFloat() } @@ -336,8 +336,8 @@ }  unittest test {-  [Base<Int>&Base<Formatted>] value <- Value1.create()-  \ Testing.checkEquals(value.get(),1)+  [Base<Int> & Base<Formatted>] value <- Value1.create()+  \ Testing.checkEquals(value.get(), 1) }  @value interface Base<|#x> {@@ -380,8 +380,8 @@ }  unittest test {-  [Base<AsBool>&Base<Formatted>] value <- Value1.create()-  \ Testing.checkEquals(value?Base<Formatted>.get().formatted(),"1")+  [Base<AsBool> & Base<Formatted>] value <- Value1.create()+  \ Testing.checkEquals(value?Base<Formatted>.get().formatted(), "1") }  @value interface Base<|#x> {@@ -436,7 +436,7 @@ }  define Value {-  call () {}+  call () { } }  concrete Test {@@ -469,7 +469,7 @@   } } -concrete Test {}+concrete Test { }   @@ -493,7 +493,7 @@ }  define Value {-  call () {}+  call () { }    create () {     return Value{}@@ -530,7 +530,7 @@   } } -concrete Test {}+concrete Test { }   testcase "convert arg" {@@ -552,7 +552,7 @@ }  define Value {-  call () {}+  call () { }    create () {     return Value{}@@ -575,11 +575,11 @@   require "does not refine Value" } -@value interface Base {}+@value interface Base { } -concrete Value {}+concrete Value { } -define Value {}+define Value { }  define Test {   @type convert (Base) -> (Value)@@ -588,7 +588,7 @@   } } -concrete Test {}+concrete Test { }   testcase "bad instance in param" {@@ -606,14 +606,14 @@   #x defines Equals<#x> } -define Value {}+define Value { }  concrete Call {   @type call<#x> () -> () }  define Call {-  call () {}+  call () { } }  @@ -629,7 +629,7 @@   } } -concrete Test {}+concrete Test { }   testcase "self in @category function" {@@ -644,7 +644,7 @@   } } -concrete Test {}+concrete Test { }   testcase "large dispatch tables" {@@ -652,47 +652,47 @@ }  unittest callDispatch {-  \ Testing.checkEquals(Type.new().get(),00)-  \ Testing.checkEquals(Type.new().get01(),01)-  \ Testing.checkEquals(Type.new().get02(),02)-  \ Testing.checkEquals(Type.new().get03(),03)-  \ Testing.checkEquals(Type.new().get04(),04)-  \ Testing.checkEquals(Type.new().get05(),05)-  \ Testing.checkEquals(Type.new().get06(),06)-  \ Testing.checkEquals(Type.new().get07(),07)-  \ Testing.checkEquals(Type.new().get08(),08)-  \ Testing.checkEquals(Type.new().get09(),09)-  \ Testing.checkEquals(Type.new().get10(),10)-  \ Testing.checkEquals(Type.new().get11(),11)-  \ Testing.checkEquals(Type.new().get12(),12)-  \ Testing.checkEquals(Type.new().get13(),13)-  \ Testing.checkEquals(Type.new().get14(),14)-  \ Testing.checkEquals(Type.new().get15(),15)-  \ Testing.checkEquals(Type.new().get16(),16)-  \ Testing.checkEquals(Type.new().get17(),17)-  \ Testing.checkEquals(Type.new().get18(),18)+  \ Testing.checkEquals(Type.new().get(), 00)+  \ Testing.checkEquals(Type.new().get01(), 01)+  \ Testing.checkEquals(Type.new().get02(), 02)+  \ Testing.checkEquals(Type.new().get03(), 03)+  \ Testing.checkEquals(Type.new().get04(), 04)+  \ Testing.checkEquals(Type.new().get05(), 05)+  \ Testing.checkEquals(Type.new().get06(), 06)+  \ Testing.checkEquals(Type.new().get07(), 07)+  \ Testing.checkEquals(Type.new().get08(), 08)+  \ Testing.checkEquals(Type.new().get09(), 09)+  \ Testing.checkEquals(Type.new().get10(), 10)+  \ Testing.checkEquals(Type.new().get11(), 11)+  \ Testing.checkEquals(Type.new().get12(), 12)+  \ Testing.checkEquals(Type.new().get13(), 13)+  \ Testing.checkEquals(Type.new().get14(), 14)+  \ Testing.checkEquals(Type.new().get15(), 15)+  \ Testing.checkEquals(Type.new().get16(), 16)+  \ Testing.checkEquals(Type.new().get17(), 17)+  \ Testing.checkEquals(Type.new().get18(), 18) }  unittest reduceBuiltin {-  \ Testing.checkPresent(reduce<Type,Type>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base01>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base02>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base03>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base04>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base05>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base06>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base07>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base08>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base09>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base10>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base11>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base12>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base13>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base14>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base15>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base16>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base17>(Type.new()))-  \ Testing.checkPresent(reduce<Type,Base18>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Type>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base01>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base02>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base03>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base04>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base05>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base06>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base07>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base08>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base09>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base10>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base11>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base12>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base13>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base14>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base15>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base16>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base17>(Type.new()))+  \ Testing.checkPresent(reduce<Type, Base18>(Type.new())) }  concrete Type {@@ -774,7 +774,7 @@   execute (Formatted) -> () } -concrete Test {}+concrete Test { }  define Test {   @type test<#x>@@ -799,7 +799,7 @@   execute (Formatted) -> () } -concrete Test {}+concrete Test { }  define Test {   @type test<#x>@@ -826,7 +826,7 @@   execute () -> (String) } -concrete Test {}+concrete Test { }  define Test {   @type test<#x>@@ -853,7 +853,7 @@   execute () -> (String) } -concrete Test {}+concrete Test { }  define Test {   @type test<#x>@@ -871,12 +871,12 @@ }  unittest test {-  \ Testing.checkEquals(Value.create().call(1,"mess",2,"age"),"message")+  \ Testing.checkEquals(Value.create().call(1, "mess", 2, "age"), "message") }  concrete Value {   @type create () -> (Value)-  @value call (Int,String,any,Formatted) -> (String)+  @value call (Int, String, any, Formatted) -> (String) }  define Value {@@ -884,7 +884,7 @@     return Value{}   } -  call (_,x,_,y) {+  call (_, x, _, y) {     return x+y.formatted()   } }@@ -895,19 +895,19 @@ }  unittest sameType {-  \ Testing.checkEquals(Value<Int>.sameType(),"Value<Int>")+  \ Testing.checkEquals(Value<Int>.sameType(), "Value<Int>") }  unittest sameValue {-  \ Testing.checkEquals(Value<Int>.create().sameValue(),"Value<Int>")+  \ Testing.checkEquals(Value<Int>.create().sameValue(), "Value<Int>") }  unittest diffType {-  \ Testing.checkEquals(Value<Int>.diffType<String>(),"Value<String>")+  \ Testing.checkEquals(Value<Int>.diffType<String>(), "Value<String>") }  unittest diffValue {-  \ Testing.checkEquals(Value<Int>.create().diffValue<String>(),"Value<String>")+  \ Testing.checkEquals(Value<Int>.create().diffValue<String>(), "Value<String>") }  concrete Value<#x> {@@ -942,5 +942,99 @@    diffValue () {     return Value<#y>.call()+  }+}+++testcase "cannot use @category function as @type function" {+  error+  require "something"+  require "category"+}++concrete Test { }++define Test {+  @category something () -> ()+  something () { }++  @category test () -> ()+  test () {+    \ Test.something()+  }+}+++testcase "cannot use @category function as @value function" {+  error+  require "something"+  require "category"+}++concrete Test { }++define Test {+  @category something () -> ()+  something () { }++  @category test () -> ()+  test () {+    \ Test{ }.something()+  }+}+++testcase "cannot use @type function as @value function" {+  error+  require "something"+  require "value"+}++concrete Test { }++define Test {+  @type something () -> ()+  something () { }++  @category test () -> ()+  test () {+    \ Test{ }.something()+  }+}+++testcase "cannot use @value function as @type function" {+  error+  require "something"+  require "type"+}++concrete Test { }++define Test {+  @value something () -> ()+  something () { }++  @category test () -> ()+  test () {+    \ Test.something()+  }+}+++testcase "cannot implicitly use @value function as @type function" {+  error+  require "something"+}++concrete Test { }++define Test {+  @value something () -> ()+  something () { }++  @type test () -> ()+  test () {+    \ something()   } }
tests/function-merging.0rt view
@@ -50,7 +50,7 @@   require "Interface2" } -@value interface Interface {}+@value interface Interface { }  @value interface Interface2 {   refines Interface@@ -108,7 +108,7 @@   require "Interface2" } -@value interface Interface {}+@value interface Interface { }  @value interface Interface2 {   refines Interface@@ -144,14 +144,14 @@   call (String) -> () } -concrete Type {}+concrete Type { }  define Type {   refines Base0   refines Base1    @value call (Formatted) -> ()-  call (_) {}+  call (_) { } }  @@ -175,7 +175,7 @@   refines Base1    @value call (Formatted) -> ()-  call (_) {}+  call (_) { } }  @@ -200,7 +200,7 @@  define Type {   @value call (any) -> ()-  call (_) {}+  call (_) { } }  @@ -224,7 +224,7 @@   refines Base0   refines Base1 -  call (_) {}+  call (_) { } }  @@ -252,7 +252,7 @@  define Type {   @value call (Formatted) -> ()-  call (_) {}+  call (_) { } }  @@ -280,7 +280,7 @@   refines Base0   refines Base1 -  call (_) {}+  call (_) { } }  @@ -316,7 +316,7 @@   refines Base3    @value call (any) -> ()-  call (_) {}+  call (_) { } }  @@ -356,5 +356,5 @@   refines Base2   refines Base3 -  call (_) {}+  call (_) { } }
+ tests/function-visibility.0rt view
@@ -0,0 +1,419 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "visibility bad types" {+  error+  require "visibility"+  require "#x"+  require "Foo"+}++concrete Test {+  visibility Append<#x>, Foo+}++define Test { }+++testcase "visibility filters not checked" {+  compiles+}++concrete Test<#x> {+  #x requires Order<#x>++  visibility Test<Int>+}++define Test { }+++testcase "visibility disallows contravariant" {+  error+  require "visibility"+  require "#x"+  require "covariant"+}++concrete Test<#x|> {+  visibility #x+}++define Test { }+++testcase "visibility allows covariant" {+  compiles+}++concrete Test<|#x> {+  visibility #x+}++define Test { }+++testcase "visibility allowed types" {+  compiles+}++concrete Test<#x> {+  visibility [Int | Char], #self+  visibility _+  visibility #x, Test<#x>+}++define Test { }+++testcase "restricted visibility not allowed for @category" {+  error+  require "visibility"+  require "foo"+}++concrete Test {+  visibility all++  @category foo () -> ()+}++define Test {+  foo () { }+}+++testcase "restricted visibility not allowed for merge" {+  error+  require "visibility"+  require "default"+}++concrete Test {+  defines Default++  visibility all++  @type default () -> (Test)+}++define Test {+  default () { return #self{ } }+}+++testcase "restricted visibility not broken by internal merge" {+  compiles+}++concrete Test {+  visibility all++  @type default () -> (Test)+}++define Test {+  @type default () -> (Test)+  default () {+    return #self{ }+  }+}+++testcase "restricted visibility ignored in own category" {+  compiles+}++concrete Test {+  visibility all++  @type default () -> (Test)+}++define Test {+  default () {+    return #self{ }+  }++  @type foo () -> ()+  foo () {+    \ default()+  }++  @category bar () -> ()+  bar () {+    \ Test.default()+  }+}+++testcase "restricted visibility ignored in unittest" {+  success+}++unittest test {+  \ Test.default()+}++concrete Test {+  visibility all++  @type default () -> (Test)+}++define Test {+  default () {+    return #self{ }+  }+}+++testcase "visibilty checks correct conversion direction" {+  compiles+}++@value interface Base<|#x> { }++concrete Test {+  visibility Base<Formatted>++  @type call () -> ()+}++define Test {+  call () { }+}++concrete Value {+  refines Base<String>++  @type test () -> ()+}++define Value {+  test () {+    \ Test.call()+  }+}+++testcase "visibilty checked in @category function" {+  error+  require "visibility"+  require "call"+}++concrete Test {+  visibility Value++  @type call () -> ()+}++define Test {+  call () { }+}++concrete Value {+  @category test () -> ()+}++define Value {+  test () {+    \ Test.call()+  }+}+++testcase "visibilty checked in @category member" {+  error+  require "visibility"+  require "call"+}++concrete Test {+  visibility Value++  @type call () -> (Int)+}++define Test {+  call () {+    return 1+  }+}++concrete Value { }++define Value {+  @category Int value <- Test.call()+}+++testcase "visibilty checked in @category function with reset" {+  compiles+}++concrete Test {+  visibility Value+  visibility _++  @type call () -> ()+}++define Test {+  call () { }+}++concrete Value {+  @category test () -> ()+}++define Value {+  test () {+    \ Test.call()+  }+}+++testcase "visibility handles #self" {+  error+  require "visibility"+  require "Order<Test>"+}++concrete Test {+  visibility Order<#self>++  @type call () -> ()+}++define Test {+  call () { }+}++concrete Value {+  refines Order<Int>+}++define Value {+  next () {+    \ Test.call()+    return empty+  }++  get () {+    return 1+  }+}+++testcase "visibility handles params" {+  error+  require "visibility"+  require "Append<Int>"+}++concrete Test<#x> {+  visibility Append<#x>++  @type call () -> ()+}++define Test {+  call () { }+}++concrete Value {+  refines Append<String>+}++define Value {+  append (_) {+    \ Test<Int>.call()+    return self+  }+}+++testcase "visibilty allows any" {+  compiles+}++@value interface Base { }++concrete Test {+  visibility String, Int, Base, Bool++  @type call () -> ()+}++define Test {+  call () { }+}++concrete Value {+  refines Base++  @type test () -> ()+}++define Value {+  test () {+    \ Test.call()+  }+}+++testcase "conversion can change visibility" {+  success+}++unittest test {+  \ Test.test()+}++@value interface Base<|#x> { }++concrete Value<|#x> {+  @type new () -> (#self)++  visibility Base<#x>++  @value call () -> ()+}++define Value {+  new () {+    return #self{ }+  }++  call () { }+}++concrete Test {+  refines Base<Formatted>++  @type test () -> ()+}++define Test {+  test () {+    Value<Int> value <- Value<Int>.new()+    \ value?Value<Formatted>.call()+  }+}
+ tests/identify.0rt view
@@ -0,0 +1,275 @@+/* -----------------------------------------------------------------------------+Copyright 2023 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 "identifier comparisons" {+  success+}++unittest boxed {+  String value1 <- "value"+  String value2 <- "value"+  Identifier<String> id1 <- `identify` value1+  Identifier<String> id2 <- `identify` value2+  $Hidden[value1, value2]$++  \ Testing.checkTrue((id1 < id2) ^ (id2 < id1))+  \ Testing.checkTrue((id1 > id2) ^ (id2 > id1))+  \ Testing.checkTrue((id1 <= id2) ^ (id2 <= id1))+  \ Testing.checkTrue((id1 >= id2) ^ (id2 >= id1))++  \ Testing.checkTrue(id1 <= id1)+  \ Testing.checkTrue(id1 >= id1)+  \ Testing.checkTrue(id1 == id1)++  \ Testing.checkFalse(id1 == id2)+  \ Testing.checkTrue(id1 != id2)+}++unittest unboxed {+  Int value1 <- 1+  Int value2 <- 2+  Int value3 <- 1+  Identifier<Int> id1 <- identify(value1)+  Identifier<Int> id2 <- identify(value2)+  Identifier<Int> id3 <- identify(value3)+  $Hidden[value1, value2, value3]$++  \ Testing.checkTrue((id1 < id2) ^ (id2 < id1))+  \ Testing.checkTrue((id1 > id2) ^ (id2 > id1))+  \ Testing.checkTrue((id1 <= id2) ^ (id2 <= id1))+  \ Testing.checkTrue((id1 >= id2) ^ (id2 >= id1))++  \ Testing.checkTrue(id1 <= id1)+  \ Testing.checkTrue(id1 >= id1)+  \ Testing.checkTrue(id1 == id1)++  \ Testing.checkFalse(id1 == id2)+  \ Testing.checkTrue(id1 != id2)++  \ Testing.checkTrue(id1 == id3)+}++unittest differentTypes {+  String value1 <- "value"+  Int value2 <- 2+  Identifier<String> id1 <- identify(value1)+  Identifier<Int> id2 <- identify(value2)+  $Hidden[value1, value2]$++  \ Testing.checkTrue((id1 < id2) ^ (id2 < id1))+  \ Testing.checkTrue((id1 > id2) ^ (id2 > id1))+  \ Testing.checkTrue((id1 <= id2) ^ (id2 <= id1))+  \ Testing.checkTrue((id1 >= id2) ^ (id2 >= id1))++  \ Testing.checkFalse(id1 == id2)+  \ Testing.checkTrue(id1 != id2)+}++unittest hashing {+  String value1 <- "value"+  String value2 <- "value"+  Identifier<String> id1 <- `identify` value1+  Identifier<String> id2 <- `identify` value2+  $Hidden[value1, value2]$++  \ Testing.checkEquals(id1.hashed(), id1.hashed())+  \ Testing.checkNotEquals(id1.hashed(), id2.hashed())+}++unittest meta {+  String value1 <- "value"+  Int value2 <- 2+  Identifier<String> id1 <- identify(value1)+  Identifier<Int> id2 <- identify(value2)+  $Hidden[value1, value2]$++  \ Testing.checkTrue(id1 == `identify` id1)+  \ Testing.checkTrue(id2 == `identify` id2)+  \ Testing.checkFalse(`identify` id1 == `identify` id2)+}++unittest formatted {+  String value1 <- "value"+  String value2 <- "value"+  Identifier<String> id1 <- `identify` value1+  Identifier<String> id2 <- `identify` value2+  $Hidden[value1, value2]$++  \ Testing.checkEquals(id1.formatted(), id1.formatted())+  \ Testing.checkNotEquals(id1.formatted(), id2.formatted())++  \ Testing.checkEquals((`identify` empty).formatted(), "0000000000000000")+}++unittest equals {+  String value1 <- "value"+  String value2 <- "value"+  Identifier<String> id1 <- `identify` value1+  Identifier<String> id2 <- `identify` value2+  $Hidden[value1, value2]$++  \ Testing.checkTrue(id1 `Identifier<any>.equals` id1)+  \ Testing.checkFalse(id1 `Identifier<any>.equals` id2)+}++unittest lessThan {+  String value1 <- "value"+  String value2 <- "value"+  Identifier<String> id1 <- `identify` value1+  Identifier<String> id2 <- `identify` value2+  $Hidden[value1, value2]$++  \ Testing.checkFalse(id1 `Identifier<any>.lessThan` id1)+  \ Testing.checkTrue((id1 `Identifier<any>.lessThan` id2) ^ (id2 `Identifier<any>.lessThan` id1))+}++unittest swap {+  String value1 <- "value"+  String value2 <- "value"+  Identifier<String> id1 <- `identify` value1+  Identifier<String> id2 <- `identify` value2+  $Hidden[value1, value2]$+  Identifier<String> id3 <- id1++  \ Testing.checkTrue(id1 == id3)+  \ Testing.checkFalse(id2 == id3)+  id1 <-> id2+  \ Testing.checkFalse(id1 == id3)+  \ Testing.checkTrue(id2 == id3)+}++unittest reduceTest {+  Identifier<String> id <- `identify` "value"+  \ Testing.checkEquals<Identifier<any>>(reduce<Identifier<String>, Identifier<Formatted>>(id), id)+  \ Testing.checkEquals<Identifier<any>>(reduce<Identifier<String>, Identifier<Int>>(id), empty)+  \ Testing.checkEquals<Identifier<any>>(reduce<Identifier<Formatted>, Identifier<String>>(id), empty)+}+++testcase "bad identifier conversion" {+  error+  require "Identifier<String>"+}++unittest test {+  Identifier<Int> value <- identify("value")+}+++testcase "identifier variable storage" {+  success+}++unittest test {+  \ Test.new().run()+}++concrete Test {+  @type new () -> (Test)+  @value run () -> ()+}++define Test {+  @value Identifier<String> valueId+  @value optional Identifier<String> optionalValueId+  @value weak Identifier<String> weakValueId++  @category Identifier<String> categoryId <- `identify` "value"+  @category optional Identifier<String> optionalCategoryId <- categoryId+  @category weak Identifier<String> weakCategoryId <- categoryId++  new () {+    Identifier<String> valueId <- `identify` "value"+    return Test{ valueId, valueId, valueId }+  }++  run () {+    // @value vs. local+    scoped {+      Identifier<String> localId <- valueId+      optional Identifier<String> optionalLocalId <- optionalValueId+      weak Identifier<String> weakLocalId <- weakValueId+    } in {+      \ Testing.checkEquals<Identifier<any>>(localId, valueId)+      \ Testing.checkEquals<Identifier<any>>(optionalLocalId, optionalValueId)+      \ Testing.checkEquals<Identifier<any>>(`strong` weakLocalId, `strong` weakLocalId)+    }+    // @category vs. local+    scoped {+      Identifier<String> localId <- categoryId+      optional Identifier<String> optionalLocalId <- optionalCategoryId+      weak Identifier<String> weakLocalId <- weakCategoryId+    } in {+      \ Testing.checkEquals<Identifier<any>>(localId, categoryId)+      \ Testing.checkEquals<Identifier<any>>(optionalLocalId, optionalCategoryId)+      \ Testing.checkEquals<Identifier<any>>(`strong` weakLocalId, `strong` weakLocalId)+    }+  }+}+++testcase "disallow identify on weak" {+  error+  require "[Ww]eak"+}++unittest test {+  weak String value <- empty+  \ identify(value)+}+++testcase "disallow identify with params" {+  error+  require "param"+}++unittest test {+  \ identify<Formatted>("value")+}+++testcase "too many args to identify" {+  error+  require "arg"+}++unittest test {+  \ identify("value", 123)+}+++testcase "too many returns passed to to identify" {+  error+  require "return"+  require "arg"+}++unittest test {+  \ identify(Helper.foo())+}++concrete Helper {+  @type foo () -> (Int, Int)+}++define Helper {+  foo () {+    return 1, 2+  }+}
tests/immutable.0rt view
@@ -168,7 +168,7 @@   require "value2" } -@value interface Foo {}+@value interface Foo { }  concrete Test {   immutable@@ -204,16 +204,16 @@   require "value" } -@value interface Foo {}+@value interface Foo { } -@value interface Bar {}+@value interface Bar { }  concrete Test {   immutable }  define Test {-  @value [Foo&Bar] value+  @value [Foo & Bar] value }  @@ -221,7 +221,7 @@   compiles } -@value interface Foo {}+@value interface Foo { }  @value interface Bar {   immutable@@ -232,7 +232,7 @@ }  define Test {-  @value [Foo&Bar] value+  @value [Foo & Bar] value }  @@ -242,7 +242,7 @@   require "value" } -@value interface Foo {}+@value interface Foo { }  @value interface Bar {   immutable@@ -253,7 +253,7 @@ }  define Test {-  @value [Foo|Bar] value+  @value [Foo | Bar] value }  @@ -274,7 +274,7 @@ }  define Test {-  @value [Foo|Bar] value+  @value [Foo | Bar] value }  @@ -373,7 +373,7 @@   require "Foo" } -@value interface Foo {}+@value interface Foo { }  concrete Test<#x> {   #x immutable@@ -421,7 +421,7 @@   require "Foo" } -@value interface Foo {}+@value interface Foo { }  concrete Test {   @type call<#x>@@ -474,9 +474,9 @@   immutable } -@value interface Foo {}+@value interface Foo { } -concrete Test {}+concrete Test { }  define Test {   refines Base@@ -497,9 +497,9 @@   immutable } -@value interface Foo {}+@value interface Foo { } -concrete Test {}+concrete Test { }  define Test {   defines Base
tests/inference.0rt view
@@ -21,23 +21,23 @@ }  unittest test {-  Int value1, String value2 <- Test.get<?,?>(10,"message")-  \ Testing.checkEquals<?>(value1,10)-  \ Testing.checkEquals<?>(value2,"message")+  Int value1, String value2 <- Test.get<?, ?>(10, "message")+  \ Testing.checkEquals<?>(value1, 10)+  \ Testing.checkEquals<?>(value2, "message") }  unittest testImplicit {-  Int value1, String value2 <- Test.get(10,"message")-  \ Testing.checkEquals<?>(value1,10)-  \ Testing.checkEquals<?>(value2,"message")+  Int value1, String value2 <- Test.get(10, "message")+  \ Testing.checkEquals<?>(value1, 10)+  \ Testing.checkEquals<?>(value2, "message") }  concrete Test {-  @type get<#x,#y> (#x,#y) -> (#x,#y)+  @type get<#x, #y> (#x, #y) -> (#x, #y) }  define Test {-  get (x,y) {+  get (x, y) {     return x, y   } }@@ -50,15 +50,15 @@ }  unittest test {-  Int value1, String value2 <- Test.get<?>(10,"message")+  Int value1, String value2 <- Test.get<?>(10, "message") }  concrete Test {-  @type get<#x,#y> (#x,#y) -> (#x,#y)+  @type get<#x, #y> (#x, #y) -> (#x, #y) }  define Test {-  get (x,y) {+  get (x, y) {     return x, y   } }@@ -192,7 +192,7 @@ }  unittest test {-  Type<Int> value <- Test.get<?>(Type<Int>.create(),"bad")+  Type<Int> value <- Test.get<?>(Type<Int>.create(), "bad") }  concrete Type<#x> {@@ -206,11 +206,11 @@ }  concrete Test {-  @type get<#x> (Type<#x>,#x) -> (Type<#x>)+  @type get<#x> (Type<#x>, #x) -> (Type<#x>) }  define Test {-  get (x,_) {+  get (x, _) {     return x   } }@@ -256,7 +256,7 @@ }  unittest test {-  \ Test.get<Formatted,?>(Type<String>.new())+  \ Test.get<Formatted, ?>(Type<String>.new()) }  concrete Type<#x> {@@ -268,7 +268,7 @@ }  concrete Test {-  @type get<#y,#x>+  @type get<#y, #x>     #x allows #y   (Type<#x>) -> (Type<#x>) }@@ -348,7 +348,7 @@ unittest test {   Type<String> x <- Type<String>.create()   Type<String> y <- Type<String>.create()-  \ Test.get<?,?>(x,y)+  \ Test.get<?, ?>(x, y) }  concrete Type<#x> {@@ -362,14 +362,14 @@ }  concrete Test {-  @type get<#x,#y>+  @type get<#x, #y>     #x defines LessThan<#y>     #y defines LessThan<#x>-  (Type<#x>,Type<#y>) -> ()+  (Type<#x>, Type<#y>) -> () }  define Test {-  get (_,_) {}+  get (_, _) { } }  @@ -379,13 +379,13 @@  unittest test {   Type z <- Type.create()-  \ Test.get<?,?,?>(z,1,"message")+  \ Test.get<?, ?, ?>(z, 1, "message") } -@type interface Base<#x,#y> {}+@type interface Base<#x, #y> { }  concrete Type {-  defines Base<Int,String>+  defines Base<Int, String>   @type create () -> (Type) } @@ -396,13 +396,13 @@ }  concrete Test {-  @type get<#z,#x,#y>-    #z defines Base<#x,#y>-  (#z,#x,#y) -> ()+  @type get<#z, #x, #y>+    #z defines Base<#x, #y>+  (#z, #x, #y) -> () }  define Test {-  get (_,_,_) {}+  get (_, _, _) { } }  @@ -411,7 +411,7 @@ }  concrete Test {-  @type call<#x,#y> (Convert<#x,#y>) -> (#x,#y)+  @type call<#x, #y> (Convert<#x, #y>) -> (#x, #y) }  define Test {@@ -421,8 +421,8 @@    @value run () -> ()   run () {-    any x1, all y1 <- call<?,?>(Convert<any,all>.create())-    all x2, any y2 <- call<?,?>(Convert<all,any>.create())+    any x1, all y1 <- call<?, ?>(Convert<any, all>.create())+    all x2, any y2 <- call<?, ?>(Convert<all, any>.create())   } } @@ -438,7 +438,7 @@   testcase "dependent implicit param inferred from requires" {-  crash+  failure   require "m e s s a g e" } @@ -452,16 +452,16 @@  define Type {   run () {-    \ call<?,?>("message")-    \ call<String,?>("message")+    \ call<?, ?>("message")+    \ call<String, ?>("message")   } -  @type call<#x,#c>+  @type call<#x, #c>     #c requires Formatted     #x requires DefaultOrder<#c>   (#x) -> ()   call (value) {-    [Append<Formatted>&Build<String>] builder <- String.builder()+    [Append<Formatted> & Build<String>] builder <- String.builder()     traverse (value.defaultOrder() -> #c char) {       \ builder.append(char).append(" ")     }@@ -471,7 +471,7 @@   testcase "dependent implicit param inferred from defines" {-  crash+  failure   require "String" } @@ -485,11 +485,11 @@  define Type {   run () {-    \ call<?,?>("message")-    \ call<String,?>("message")+    \ call<?, ?>("message")+    \ call<String, ?>("message")   } -  @type call<#x,#c>+  @type call<#x, #c>     #x defines LessThan<#c>   (#x) -> ()   call (value) {@@ -499,7 +499,7 @@   testcase "dependent implicit param inferred from allows" {-  crash+  failure   require "String" } @@ -513,11 +513,11 @@  define Type {   run () {-    \ call<?,?>("message")-    \ call<String,?>("message")+    \ call<?, ?>("message")+    \ call<String, ?>("message")   } -  @type call<#x,#c>+  @type call<#x, #c>     #x allows #c   (#x) -> ()   call (value) {@@ -527,7 +527,7 @@   testcase "dependent implicit param inferred from reverse allows" {-  crash+  failure   require "String" } @@ -541,11 +541,11 @@  define Type {   run () {-    \ call<?,?>("message")-    \ call<String,?>("message")+    \ call<?, ?>("message")+    \ call<String, ?>("message")   } -  @type call<#x,#c>+  @type call<#x, #c>     #c allows #x   (#x) -> ()   call (value) {@@ -555,7 +555,7 @@   testcase "dependent implicit param inferred from reverse requires" {-  crash+  failure   require "String" } @@ -569,11 +569,11 @@  define Type {   run () {-    \ call<?,?>("message")-    \ call<String,?>("message")+    \ call<?, ?>("message")+    \ call<String, ?>("message")   } -  @type call<#x,#c>+  @type call<#x, #c>     #c requires #x   (#x) -> ()   call (value) {@@ -608,7 +608,7 @@   testcase "filter guess merged with arg guess" {-  crash+  failure   require "String"   exclude "Formatted" }@@ -642,9 +642,9 @@   \ Test.call<?>(Type.create()) } -@value interface Base1<|#x> {}+@value interface Base1<|#x> { } -@value interface Base2<|#x> {}+@value interface Base2<|#x> { }  concrete Type {   refines Base1<Int>@@ -660,7 +660,7 @@ }  concrete Test {-  @type call<#x> ([Base1<#x>|Base2<#x>]) -> ()+  @type call<#x> ([Base1<#x> | Base2<#x>]) -> () }  define Test {@@ -678,9 +678,9 @@   \ Test.call<?>(Type.create()) } -@value interface Base1<#x> {}+@value interface Base1<#x> { } -@value interface Base2<#x> {}+@value interface Base2<#x> { }  concrete Type {   refines Base1<Int>@@ -696,7 +696,7 @@ }  concrete Test {-  @type call<#x> ([Base1<#x>&Base2<#x>]) -> ()+  @type call<#x> ([Base1<#x> & Base2<#x>]) -> () }  define Test {@@ -705,7 +705,7 @@   testcase "variance allows guesses to be merged using meta type" {-  crash+  failure   require "\[Int\|String\]" } @@ -713,9 +713,9 @@   \ Test.call<?>(Type.create()) } -@value interface Base1<|#x> {}+@value interface Base1<|#x> { } -@value interface Base2<|#x> {}+@value interface Base2<|#x> { }  concrete Type {   refines Base1<Int>@@ -731,7 +731,7 @@ }  concrete Test {-  @type call<#x> ([Base1<#x>&Base2<#x>]) -> ()+  @type call<#x> ([Base1<#x> & Base2<#x>]) -> () }  define Test {@@ -742,7 +742,7 @@   testcase "alternative guess eliminated by filter" {-  crash+  failure   require "Int" } @@ -750,9 +750,9 @@   \ Test.call<?>(Type.create()) } -@value interface Base1<|#x> {}+@value interface Base1<|#x> { } -@value interface Base2<|#x> {}+@value interface Base2<|#x> { }  concrete Type {   refines Base1<Int>@@ -770,7 +770,7 @@ concrete Test {   @type call<#x>     #x requires AsChar-  ([Base1<#x>|Base2<#x>]) -> ()+  ([Base1<#x> | Base2<#x>]) -> () }  define Test {
tests/infix-functions.0rt view
@@ -28,11 +28,11 @@ }  concrete Test {-  @category add (Int,Int) -> (Int)+  @category add (Int, Int) -> (Int) }  define Test {-  add (x,y) {+  add (x, y) {     return x + y   } }@@ -50,11 +50,11 @@ }  concrete Test {-  @type add (Int,Int) -> (Int)+  @type add (Int, Int) -> (Int) }  define Test {-  add (x,y) {+  add (x, y) {     return x + y   } }@@ -73,7 +73,7 @@  concrete Arithmetic {   @type create () -> (Arithmetic)-  @value add (Int,Int) -> (Int)+  @value add (Int, Int) -> (Int) }  define Arithmetic {@@ -81,7 +81,7 @@     return Arithmetic{ }   } -  add (x,y) {+  add (x, y) {     return x + y   } }@@ -96,8 +96,8 @@ }  define Test {-  @type add (Int,Int) -> (Int)-  add (x,y) {+  @type add (Int, Int) -> (Int)+  add (x, y) {     return x + y   } @@ -126,11 +126,11 @@ }  concrete Test {-  @category add (Int,Int) -> (Int)+  @category add (Int, Int) -> (Int) }  define Test {-  add (x,y) {+  add (x, y) {     return x + y   } }@@ -148,11 +148,11 @@ }  concrete Test {-  @category add (Int,Int) -> (Int)+  @category add (Int, Int) -> (Int) }  define Test {-  add (x,y) {+  add (x, y) {     return x + y   } }@@ -172,20 +172,20 @@  define Test {   check () {-    \ Testing.checkEquals(1 `one` 2 `two` 4,5)+    \ Testing.checkEquals(1 `one` 2 `two` 4, 5)   } -  @type one (Int,Int) -> (Int)-  one (x,y) {-    \ Testing.checkEquals(x,1)-    \ Testing.checkEquals(y,2)+  @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)+  @type two (Int, Int) -> (Int)+  two (x, y) {+    \ Testing.checkEquals(x, 3)+    \ Testing.checkEquals(y, 4)     return 5   } }
tests/infix-operations.0rt view
@@ -21,55 +21,55 @@ }  unittest plus {-  \ Testing.checkEquals(8 + 2,10)+  \ Testing.checkEquals(8 + 2, 10) }  unittest minus {-  \ Testing.checkEquals(8 - 2,6)+  \ Testing.checkEquals(8 - 2, 6) }  unittest times {-  \ Testing.checkEquals(8 * 2,16)+  \ Testing.checkEquals(8 * 2, 16) }  unittest divide {-  \ Testing.checkEquals(8 / 2,4)+  \ Testing.checkEquals(8 / 2, 4) }  unittest modulo {-  \ Testing.checkEquals(8 % 2,0)+  \ Testing.checkEquals(8 % 2, 0) }  unittest left {-  \ Testing.checkEquals(1 << 2,4)+  \ Testing.checkEquals(1 << 2, 4) }  unittest right {-  \ Testing.checkEquals(7 >> 1,3)+  \ Testing.checkEquals(7 >> 1, 3) }  unittest xor {-  \ Testing.checkEquals(7 ^ 2 ,5)+  \ Testing.checkEquals(7 ^ 2 , 5) }  unittest and {-  \ Testing.checkEquals(7 & ~2,5)+  \ Testing.checkEquals(7 & ~2, 5) }  unittest or {-  \ Testing.checkEquals(5 | 2 ,7)+  \ Testing.checkEquals(5 | 2 , 7) }  unittest arithmetic {-  \ Testing.checkEquals(\x10 + 1 * 2 - 8 / 2 - 3 % 2,13)+  \ Testing.checkEquals(\x10 + 1 * 2 - 8 / 2 - 3 % 2, 13) }  unittest bitwise {-  \ Testing.checkEquals(1 << 4 | 7 >> 1 & ~2,17)+  \ Testing.checkEquals(1 << 4 | 7 >> 1 & ~2, 17) }  unittest sameOperator {-  \ Testing.checkEquals(2 - 1 - 1,0)+  \ Testing.checkEquals(2 - 1 - 1, 0) }  unittest lessThan {@@ -136,14 +136,14 @@ unittest rightAssociative {   Int x <- 2   Bool y <- true && (x <- 3) == 2 || x == 3-  \ Testing.checkEquals(x,3)+  \ Testing.checkEquals(x, 3)   \ Testing.checkTrue(y) }  unittest shortCircuit {   Int x <- 2   Bool y <- true || (x <- 3) == 2 || x == 3-  \ Testing.checkEquals(x,2)+  \ Testing.checkEquals(x, 2)   \ Testing.checkTrue(y) } @@ -153,7 +153,7 @@ }  unittest precedence {-  \ Testing.checkEquals(16.0 + 1.0 * 2.0 - 8.0 / 2.0 - 3.0 / 3.0,13.0)+  \ Testing.checkEquals(16.0 + 1.0 * 2.0 - 8.0 / 2.0 - 3.0 / 3.0, 13.0) }  unittest lessThan {@@ -190,7 +190,7 @@ }  unittest add {-  \ Testing.checkEquals("x" + "y" + "z","xyz")+  \ Testing.checkEquals("x" + "y" + "z", "xyz") }  unittest lessThan {@@ -227,7 +227,7 @@ }  unittest minus {-  \ Testing.checkEquals('z' - 'a',25)+  \ Testing.checkEquals('z' - 'a', 25) }  unittest lessThan {
tests/internal-inheritance.0rt view
@@ -96,9 +96,9 @@   success } -unittest test {}+unittest test { } -concrete Value {}+concrete Value { }  define Value {   refines Formatted@@ -108,7 +108,7 @@     return "Value"   } -  equals (_,_) {+  equals (_, _) {     return true   } }@@ -121,7 +121,7 @@ unittest test {   Value value1 <- Value.create(1)   Value value2 <- Value.create(2)-  if (Value.compare(value1,value2)) {+  if (Value.compare(value1, value2)) {     fail("Failed")   } }@@ -129,18 +129,18 @@ concrete Compare<#x> {   #x defines Equals<#x> -  @type compare (#x,#x) -> (Bool)+  @type compare (#x, #x) -> (Bool) }  define Compare {-  compare (x,y) {-    return #x.equals(x,y)+  compare (x, y) {+    return #x.equals(x, y)   } }  concrete Value {   @type create (Int) -> (Value)-  @type compare (Value,Value) -> (Bool)+  @type compare (Value, Value) -> (Bool) }  define Value {@@ -148,7 +148,7 @@    @value Int value -  equals (x,y) {+  equals (x, y) {     return x.get() == y.get()   } @@ -156,8 +156,8 @@     return Value{ x }   } -  compare (x,y) {-    return Compare<Value>.compare(x,y)+  compare (x, y) {+    return Compare<Value>.compare(x, y)   }    @value get () -> (Int)@@ -177,18 +177,18 @@ unittest test {   Value value1 <- Value.create(1)   Value value2 <- Value.create(2)-  \ Compare<Value>.compare(value1,value2)+  \ Compare<Value>.compare(value1, value2) }  concrete Compare<#x> {   #x defines Equals<#x> -  @type compare (#x,#x) -> (Bool)+  @type compare (#x, #x) -> (Bool) }  define Compare {-  compare (x,y) {-    return #x.equals(x,y)+  compare (x, y) {+    return #x.equals(x, y)   } } @@ -201,7 +201,7 @@    @value Int value -  equals (x,y) {+  equals (x, y) {     return x.get() == y.get()   } @@ -222,9 +222,9 @@   require "type interface" } -@value interface Base {}+@value interface Base { } -concrete Type {}+concrete Type { }  define Type {   defines Base@@ -241,7 +241,7 @@   call (#x) -> () } -concrete Type<|#x> {}+concrete Type<|#x> { }  define Type {   refines Base<#x>@@ -258,7 +258,7 @@   call (#x) -> () } -concrete Type<|#x> {}+concrete Type<|#x> { }  define Type {   defines Base<#x>@@ -269,7 +269,7 @@   compiles } -@value interface Base1<#x> {}+@value interface Base1<#x> { }  @value interface Base2<#x> {   refines Base1<#x>
tests/leak-check/.zeolite-module view
@@ -12,6 +12,6 @@   "lib/util" ] mode: binary {-  category: LeakTest+  category: LeakCheck   function: run }
tests/leak-check/README.md view
@@ -17,7 +17,7 @@  ```shell # The "leak" argument is important.-valgrind --leak-check=yes $ZEOLITE_PATH/tests/leak-check/LeakTest leak+valgrind --leak-check=yes $ZEOLITE_PATH/tests/leak-check/LeakCheck leak ```  You should get output that looks something like this:@@ -26,7 +26,7 @@ ==8487== Memcheck, a memory error detector ==8487== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==8487== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info-==8487== Command: tests/leak-check/LeakTest leak+==8487== Command: tests/leak-check/LeakCheck leak ==8487== ==8487== ==8487== HEAP SUMMARY:@@ -58,7 +58,7 @@  ```shell # The "race" argument is important.-$ZEOLITE_PATH/tests/leak-check/LeakTest race+$ZEOLITE_PATH/tests/leak-check/LeakCheck race ```  *Do not use `valgrind` to run in `race` mode!* The latency introduced by@@ -70,10 +70,10 @@  --- -A more comprehensive test involves leaving `LeakTest` running for an hour or so.+A more comprehensive test involves leaving `LeakCheck` running indefinitely.  ```shell-$ZEOLITE_PATH/tests/leak-check/LeakTest forever+$ZEOLITE_PATH/tests/leak-check/LeakCheck forever ```  This will cause `LeakCheck` to run for a very long time, while attempting to
tests/leak-check/leak-check.0rx view
@@ -1,20 +1,38 @@-concrete LeakTest {+/* -----------------------------------------------------------------------------+Copyright 2021-2022 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]++concrete LeakCheck {   @type run () -> () } -define LeakTest {+define LeakCheck {   @value Vector<Int> memory    run () {     if (Argv.global().size() != 2) {       \ message()     } elif (Argv.global().readAt(1) == "race") {-      \ runWith(1000,0)+      \ runWith(1000, 0)       \ BasicOutput.stderr().writeNow("no race conditions this time\n")     } elif (Argv.global().readAt(1) == "leak") {-      \ runWith(100,0)+      \ runWith(100, 0)     } elif (Argv.global().readAt(1) == "forever") {-      \ runWith(10000000,1024*1024)+      \ runWith(10000000, 1024*1024)     } else {       \ message()     }@@ -22,23 +40,23 @@    @type message () -> ()   message () {-    fail(Argv.global().readAt(0) + " [race|leak|forever]")+    fail(Argv.global().readAt(0) + " [race | leak | forever]")   } -  @type runWith (Int,Int) -> ()-  runWith (iterations,size) {-    Int threads <- Ranges:max(3,$ExprLookup[CPU_CORE_COUNT]$-1)+  @type runWith (Int, Int) -> ()+  runWith (iterations, size) {+    Int threads <- Ranges:max(3, $ExprLookup[CPU_CORE_COUNT]$-1)     ReadAt<BarrierWait> barriers <- EnumeratedBarrier.new(threads+1)     traverse (Counter.zeroIndexed(iterations) -> Int i) {-      \ doIteration<LastReference>(i,size,barriers)-      \ doIteration<Chaos>(i,size,barriers)+      \ doIteration<LastReference>(i, size, barriers)+      \ doIteration<Chaos>(i, size, barriers)     }   }    @type doIteration<#f>     #f defines ThreadFactory-  (Int,Int,ReadAt<BarrierWait>) -> ()-  doIteration (i,size,barriers) {+  (Int, Int, ReadAt<BarrierWait>) -> ()+  doIteration (i, size, barriers) {     \ BasicOutput.stderr()         .write(typename<#f>())         .write(": iteration ")@@ -46,15 +64,15 @@         .write("\n")         .flush() -    optional LeakTest original <- LeakTest{ Vector:createSize<Int>(size) }-    weak LeakTest checkedValue <- original+    optional LeakCheck original <- LeakCheck{ Vector:createSize<Int>(size) }+    weak LeakCheck checkedValue <- original     $ReadOnly[checkedValue]$      scoped {       Vector<Thread> threads <- Vector<Thread>.new()     } in {       traverse (Counter.zeroIndexed(barriers.size()-1) -> Int j) {-        \ threads.push(ProcessThread.from(#f.create(original,barriers.readAt(j+1))).start())+        \ threads.push(ProcessThread.from(#f.create(original, barriers.readAt(j+1))).start())       }        \ barriers.readAt(0).wait()@@ -71,7 +89,7 @@ }  @type interface ThreadFactory {-  create (optional LeakTest,BarrierWait) -> (Routine)+  create (optional LeakCheck, BarrierWait) -> (Routine) }  concrete LastReference {@@ -83,10 +101,10 @@    refines Routine -  @value weak LeakTest copy+  @value weak LeakCheck copy   @value BarrierWait barrier -  create (copy,barrier) {+  create (copy, barrier) {     return LastReference{ copy, barrier }   } @@ -105,23 +123,26 @@    refines Routine -  @value weak LeakTest copy+  @value weak LeakCheck copy   @value BarrierWait barrier -  create (copy,barrier) {+  create (copy, barrier) {     return Chaos{ copy, barrier }   }    run ()  {-    weak LeakTest copy1 <- empty-    weak LeakTest copy2 <- empty-    weak LeakTest copy3 <- empty-    weak LeakTest copy4 <- empty-    weak LeakTest copy5 <- empty+    weak LeakCheck copy1 <- empty+    weak LeakCheck copy2 <- empty+    weak LeakCheck copy3 <- empty+    weak LeakCheck copy4 <- empty+    weak LeakCheck copy5 <- empty     \ barrier.wait()     copy1 <- copy     copy2 <- copy1     copy3 <- copy1+    copy3 <-> copy1+    copy1 <-> copy1+    copy2 <-> copy1     copy <- empty     copy4 <- strong(copy2)     copy1 <- strong(copy3)
tests/local-rules.0rt view
@@ -52,7 +52,7 @@     $ReadOnly[foo]$   }   foo <- 2-  \ Testing.checkEquals(foo,2)+  \ Testing.checkEquals(foo, 2) }  @@ -82,7 +82,7 @@     $ReadOnly[foo]$   }   foo <- 2-  \ Testing.checkEquals(foo,2)+  \ Testing.checkEquals(foo, 2) }  @@ -97,9 +97,9 @@     foo <- 2     $ReadOnly[foo]$   }-  \ Testing.checkEquals(foo,2)+  \ Testing.checkEquals(foo, 2)   foo <- 3-  \ Testing.checkEquals(foo,3)+  \ Testing.checkEquals(foo, 3) }  @@ -151,7 +151,7 @@   cleanup {     foo <- 2   } in $ReadOnly[foo]$-  \ Testing.checkEquals(foo,2)+  \ Testing.checkEquals(foo, 2) }  @@ -181,7 +181,7 @@     $Hidden[foo]$   }   foo <- 2-  \ Testing.checkEquals(foo,2)+  \ Testing.checkEquals(foo, 2) }  @@ -240,9 +240,9 @@     foo <- 2     $Hidden[foo]$   }-  \ Testing.checkEquals(foo,2)+  \ Testing.checkEquals(foo, 2)   foo <- 3-  \ Testing.checkEquals(foo,3)+  \ Testing.checkEquals(foo, 3) }  @@ -264,7 +264,7 @@   exclude "bar" } -concrete Type {}+concrete Type { }  define Type {   $ReadOnly[foo]$@@ -286,7 +286,7 @@   exclude "bar" } -concrete Type {}+concrete Type { }  define Type {   $Hidden[foo]$@@ -307,7 +307,7 @@   require "foo.+does not exist" } -concrete Type {}+concrete Type { }  define Type {   $Hidden[foo]$@@ -321,7 +321,7 @@ }  unittest test {-  \ Testing.checkEquals(Type:get(),2)+  \ Testing.checkEquals(Type:get(), 2) }  concrete Type {@@ -347,7 +347,7 @@   exclude "bar" } -concrete Type {}+concrete Type { }  define Type {   $ReadOnly[foo]$@@ -369,7 +369,7 @@   exclude "bar" } -concrete Type {}+concrete Type { }  define Type {   $Hidden[foo]$@@ -390,7 +390,7 @@   require "foo.+does not exist" } -concrete Type {}+concrete Type { }  define Type {   $Hidden[foo]$@@ -404,7 +404,7 @@ }  unittest test {-  \ Testing.checkEquals(Type.create().get(),1)+  \ Testing.checkEquals(Type.create().get(), 1) }  concrete Type {@@ -434,7 +434,7 @@   exclude "bar" } -concrete Type {}+concrete Type { }  define Type {   $ReadOnlyExcept[bar]$@@ -456,7 +456,7 @@   exclude "bar" } -concrete Type {}+concrete Type { }  define Type {   $ReadOnlyExcept[bar]$@@ -477,7 +477,7 @@   require "foo.+read-only" } -concrete Type {}+concrete Type { }  define Type {   $ReadOnlyExcept[foo]$@@ -497,7 +497,7 @@   require compiler "ReadOnlyExcept" } -concrete Type {}+concrete Type { }  define Type {   $ReadOnlyExcept[foo]$@@ -519,7 +519,7 @@   require "foo.+does not exist" } -concrete Type {}+concrete Type { }  define Type {   $ReadOnlyExcept[foo]$
tests/local.0rp view
@@ -18,4 +18,4 @@  $ModuleOnly$ -@value interface ModuleOnly {}+@value interface ModuleOnly { }
tests/member-init.0rt view
@@ -25,7 +25,7 @@   @type Bool value <- false } -concrete Test {}+concrete Test { }   testcase "@category member from @type" {@@ -36,7 +36,7 @@   // NOTE: Executing the test ensures that C++ compilation works. } -concrete Test {}+concrete Test { }  define Test {   @category Bool value <- true@@ -56,7 +56,7 @@   // NOTE: Executing the test ensures that C++ compilation works. } -concrete Test {}+concrete Test { }  define Test {   @category Bool value <- true@@ -73,7 +73,7 @@   require "get" } -concrete Test {}+concrete Test { }  define Test {   @category Bool value <- get()@@ -90,7 +90,7 @@ }  unittest test {-  \ Testing.checkEquals(Test:get(),2)+  \ Testing.checkEquals(Test:get(), 2) }  concrete Test {@@ -126,7 +126,7 @@   } } -concrete Test {}+concrete Test { }  define Test {   @category Bool value <- Util.doNotUse()@@ -134,7 +134,7 @@   testcase "@category member init when read" {-  crash+  failure   require "do not use" } @@ -166,7 +166,7 @@   testcase "@category member init when assigned" {-  crash+  failure   require "do not use" } @@ -198,7 +198,7 @@   testcase "@category member init when ignored" {-  crash+  failure   require "do not use" } @@ -258,8 +258,8 @@   testcase "@category init cycle" {-  crash-  require "Value1|Value2"+  failure+  require "Value1 | Value2" }  unittest test {@@ -296,7 +296,7 @@   require "self" } -concrete Test {}+concrete Test { }  define Test {   @category Test value <- self@@ -308,7 +308,7 @@   require "disallowed" } -concrete Test {}+concrete Test { }  define Test {   @category Bool value <- get()@@ -325,7 +325,7 @@   require "value1.+read-only" } -concrete Test {}+concrete Test { }  define Test {   @category Int value1 <- 1@@ -338,7 +338,7 @@   require "Foo not found" } -concrete Test {}+concrete Test { }  define Test {   @category optional Foo value <- empty@@ -350,7 +350,7 @@   require "Foo not found" } -concrete Test {}+concrete Test { }  define Test {   @value Foo value@@ -362,7 +362,7 @@   require "#x not found" } -concrete Test<#x> {}+concrete Test<#x> { }  define Test {   @category optional #x value <- empty
tests/modified-storage.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2020 Kevin P. Barry+Copyright 2020,2023 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.@@ -185,7 +185,7 @@ }  concrete Test {-  @type get () -> (Value,Value)+  @type get () -> (Value, Value) }  define Test {@@ -260,7 +260,7 @@     return Test{ }   } -  call () {}+  call () { } }  @@ -271,35 +271,405 @@ unittest boxed {   String value <- "message"   weak String value2 <- value-  $ValidateRefs[value,value2]$+  $ValidateRefs[value, value2]$ }  unittest int {   Int value <- 1   weak Int value2 <- value-  $ValidateRefs[value,value2]$+  $ValidateRefs[value, value2]$ }  unittest char {   Char value <- 'a'   weak Char value2 <- value-  $ValidateRefs[value,value2]$+  $ValidateRefs[value, value2]$ }  unittest bool {   Bool value <- false   weak Bool value2 <- value-  $ValidateRefs[value,value2]$+  $ValidateRefs[value, value2]$ }  unittest float {   Float value <- 1.0   weak Float value2 <- value-  $ValidateRefs[value,value2]$+  $ValidateRefs[value, value2]$ }  unittest emptyVal {   optional all value <- empty   weak all value2 <- value-  $ValidateRefs[value,value2]$+  $ValidateRefs[value, value2]$+}+++testcase "call from empty" {+  error+  require "optional"+}++unittest test {+  \ empty.foo()+}+++testcase "inline assignment to weak" {+  success+}++unittest unboxed {+  weak Int value <- empty+  Int value2 <- (value <- 123)+  \ Testing.checkEquals(value2, 123)+  \ Testing.checkEquals(strong(value), 123)+}++unittest boxedNoRefs {+  weak String value <- empty+  \ Testing.checkEquals((value <- "message"), "message")+  \ Testing.checkEquals(strong(value), empty)+}++unittest boxedRefs {+  weak String value <- empty+  String original <- "message"+  String value2 <- (value <- original)+  \ Testing.checkEquals(value2, original)+  \ Testing.checkEquals(strong(value), original)+}++unittest weakToWeak {+  weak String value <- empty+  String original <- "message"+  weak String value2 <- original+  \ Testing.checkEquals(`strong` (value <- value2), original)+  \ Testing.checkEquals(strong(value), original)+}+++testcase "conditional inline assignment" {+  success+}++concrete Helper {+  @type notCalled () -> (all)+}++define Helper {+  notCalled () {+    fail("should not be called")+  }+}++unittest shortCircuit {+  optional Int value <- 123+  Int value2 <- (value <-| Helper.notCalled())+  \ Testing.checkEquals(value2, 123)+  \ Testing.checkEquals(value, 123)+}++unittest unboxedToUnboxed {+  optional Int value <- empty++  Int value2 <- (value <-| 123)+  \ Testing.checkEquals(value2, 123)+  \ Testing.checkEquals(value, 123)++  Int value3 <- (value <-| 456)+  \ Testing.checkEquals(value3, 123)+  \ Testing.checkEquals(value, 123)+}++unittest boxedToBoxed {+  optional String value <- empty++  String value2 <- (value <-| "message")+  \ Testing.checkEquals(value2, "message")+  \ Testing.checkEquals(value, "message")++  String value3 <- (value <-| "other")+  \ Testing.checkEquals(value3, "message")+  \ Testing.checkEquals(value, "message")+}+++testcase "conditional assignment" {+  success+}++concrete Helper {+  @type notCalled () -> (all)+}++define Helper {+  notCalled () {+    fail("should not be called")+  }+}++unittest shortCircuit {+  optional Int value <- 123+  value <-| Helper.notCalled()+  \ Testing.checkEquals(value, 123)+}++unittest unboxedToUnboxed {+  optional Int value <- empty++  value <-| 123+  \ Testing.checkEquals(value, 123)++  value <-| 456+  \ Testing.checkEquals(value, 123)+}++unittest boxedToBoxed {+  optional String value <- empty++  value <-| "message"+  \ Testing.checkEquals(value, "message")++  value <-| "other"+  \ Testing.checkEquals(value, "message")+}+++testcase "conditional inline assignment wrong return type" {+  error+  require "Formatted"+  require "Int"+}++unittest test {+  optional Formatted value <- empty+  Int value2 <- (value <-| 123)+}+++testcase "conditional inline assignment wrong return storage" {+  error+  require "storage modifier"+}++unittest test {+  optional Int value <- 123+  Int value2 <- (value <-| empty)+}+++testcase "conditional inline assignment deferred" {+  error+  require "initialized"+  require "value"+}++unittest test {+  optional Int value <- defer+  Int value2 <- (value <-| 123)+}+++testcase "conditional inline assignment required" {+  error+  require "optional"+}++unittest test {+  Int value <- 456+  Int value2 <- (value <-| 123)+}+++testcase "conditional inline assignment weak" {+  error+  require "optional"+}++unittest test {+  weak Int value <- 456+  Int value2 <- (value <-| 123)+}+++testcase "conditional assignment wrong return count" {+  error+  require "return"+}++concrete Helper {+  @type get () -> (Int, Int)+}++define Helper {+  get () {+    return 1, 2+  }+}++unittest test {+  optional Int value <- 456+  value <-| Helper.get()+}+++testcase "optional value calls" {+  success+}++concrete Helper {+  @type notCalled () -> (all)+}++define Helper {+  notCalled () {+    fail("should not be called")+  }+}++unittest nonEmpty {+  optional Int value <- 123+  \ Testing.checkEquals(value&.formatted(), "123")+}++unittest chainedCalls {+  optional Int value <- 123+  \ Testing.checkEquals(value&.formatted()&.readAt(0), '1')+}++unittest emptyValue {+  optional Int value <- empty+  \ Testing.checkEquals(value&.formatted(), empty)+}++unittest shortCircuit {+  optional String value <- empty+  \ value&.readAt(Helper.notCalled())+}+++testcase "conditional call return types become optional" {+  error+  require "storage modifier"+}++unittest test {+  optional Int value <- empty+  String value2 <- value&.formatted()+}+++testcase "conditional call not allowed for required" {+  error+  require "[Oo]ptional"+}++unittest test {+  \ "123"&.readAt(0)+}+++testcase "conditional call not allowed for weak" {+  error+  require "[Oo]ptional"+}++unittest test {+  weak String value <- empty+  \ value&.readAt(0)+}+++testcase "conditional call with multi returns" {+  success+}++concrete Value {+  @type new () -> (Value)+  @value get () -> (optional Int, Int)+}++define Value {+  new () {+    return Value{ }+  }++  get () {+    return 1, 2+  }+}++unittest chained {+  optional Value value <- Value.new()+  \ Testing.checkEquals(value&.get(){1}&.formatted(), "2")+}++unittest notCalled {+  optional Value value <- empty+  optional Int result1, optional Int result2 <- value&.get()+  \ Testing.checkEmpty(result1)+  \ Testing.checkEmpty(result2)++}+++testcase "conditional call only happens once" {+  success+}++concrete Value {+  @type new () -> (optional Value)+  @value get () -> (Int)+}++define Value {+  @category Bool used <- false++  new () {+    if (used) {+      fail("already called")+    }+    used <- true+    return Value{ }+  }++  get () {+    return 1+  }+}++unittest test {+  \ Testing.checkEquals(Value.new()&.get()&.formatted()&.readAt(0), '1')+}+++testcase "conditional call bad function name" {+  error+  require "foo"+}++unittest test {+  optional String value <- empty+  \ value&.foo()+}+++testcase "conditional call from empty" {+  error+  require "formatted"+  require "all"+}++unittest test {+  \ empty&.formatted()+}+++testcase "conditional call from converted empty" {+  success+}++unittest test {+  \ Testing.checkEmpty(empty?Formatted&.formatted()) }
tests/module-only/.zeolite-module view
@@ -3,4 +3,4 @@ private_deps: [   "internal" ]-mode: incremental {}+mode: incremental { }
tests/module-only/internal/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../../.." path: "tests/module-only/internal"-mode: incremental {}+mode: incremental { }
tests/module-only/internal/private.0rp view
@@ -18,4 +18,4 @@  $ModuleOnly$ -@value interface Type1 {}+@value interface Type1 { }
tests/module-only/internal/public.0rp view
@@ -16,4 +16,4 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -@value interface Type2 {}+@value interface Type2 { }
tests/module-only/private.0rx view
@@ -16,7 +16,7 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -concrete Test {}+concrete Test { }  define Test {   @value Type1 val1
tests/module-only2/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../.." path: "tests/module-only2"-mode: incremental {}+mode: incremental { }
tests/module-only2/private1.0rp view
@@ -18,4 +18,4 @@  $ModuleOnly$ -@value interface Type1 {}+@value interface Type1 { }
tests/module-only3/.zeolite-module view
@@ -7,4 +7,4 @@   "tests/module-only3/source1.cpp"   "tests/module-only3/source2.cpp" ]-mode: incremental {}+mode: incremental { }
tests/module-only3/internal/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../../.." path: "tests/module-only3/internal"-mode: incremental {}+mode: incremental { }
tests/module-only3/internal/private.0rp view
@@ -18,4 +18,4 @@  $ModuleOnly$ -@value interface Type1 {}+@value interface Type1 { }
tests/module-only3/internal/public.0rp view
@@ -16,4 +16,4 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -@value interface Type2 {}+@value interface Type2 { }
tests/module-only4/.zeolite-module view
@@ -7,4 +7,4 @@     requires: [Type2]   } ]-mode: incremental {}+mode: incremental { }
tests/multiple-returns.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2020-2021 Kevin P. Barry+Copyright 2020-2021,2023 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.@@ -18,11 +18,11 @@  testcase "multi return to call" {   error-  require "call.+\{Value,Value\}"+  require "call.+Value.+Value" }  @value interface Value {-  get () -> (Value,Value)+  get () -> (Value, Value)   call () -> () } @@ -33,12 +33,12 @@   } } -concrete Test {}+concrete Test { }   testcase "zero return to call" {   error-  require "call.+\{\}"+  require "call.+none" }  @value interface Value {@@ -53,7 +53,7 @@   } } -concrete Test {}+concrete Test { }   testcase "multi return assign" {@@ -68,7 +68,7 @@  concrete Test {   @type create () -> (Test)-  @value double () -> (Test,Test)+  @value double () -> (Test, Test) }  define Test {@@ -95,7 +95,7 @@     return 1, 2   } -  call (x,y) {+  call (x, y) {     if (x != 1) {       fail("Failed")     }@@ -106,26 +106,58 @@ }  concrete Test {-  @type get () -> (Int,Int)-  @type call (Int,Int) -> ()+  @type get () -> (Int, Int)+  @type call (Int, Int) -> () }  +testcase "multi return as args with params" {+  success+}++unittest testExplicit {+    \ Test.call<Int>(Test.get())+}++unittest testInferred {+    \ Test.call(Test.get())+}++define Test {+  get () {+    return 1, 2+  }++  call (x, y) {+    if (!(x `#x.lessThan` y)) {+      fail("Failed")+    }+  }+}++concrete Test {+  @type get () -> (Int, Int)+  @type call<#x>+    #x defines LessThan<#x>+  (#x, #x) -> ()+}++ testcase "return selection" {   success }  unittest correctPosition {-  \ Testing.checkEquals(Test.get(){0},123)-  \ Testing.checkEquals(Test.get(){1},"message")+  \ Testing.checkEquals(Test.get(){0}, 123)+  \ Testing.checkEquals(Test.get(){1}, "message") }  unittest chainedCall {-  \ Testing.checkEquals(Test.get(){0}.formatted(),"123")+  \ Testing.checkEquals(Test.get(){0}.formatted(), "123") }  concrete Test {-  @type get () -> (Int,String)+  @type get () -> (Int, String) }  define Test {@@ -145,7 +177,7 @@ }  concrete Test {-  @type get () -> (Int,String)+  @type get () -> (Int, String) }  define Test {
tests/named-returns.0rt view
@@ -21,13 +21,13 @@   require "value" } -@value interface Value {}+@value interface Value { } -concrete Test {}+concrete Test { }  define Test {   @value process () -> (Value)-  process () (value) {}+  process () (value) { } }  @@ -35,7 +35,7 @@   compiles } -concrete Test {}+concrete Test { }  define Test {   @value process () -> (Bool)@@ -50,7 +50,7 @@   require "value.+initialized" } -concrete Test {}+concrete Test { }  define Test {   @value process () -> (Bool)@@ -64,7 +64,7 @@   compiles } -concrete Test {}+concrete Test { }  define Test {   @value process () -> (Int)@@ -78,7 +78,7 @@   compiles } -concrete Test {}+concrete Test { }  define Test {   @value process () -> (Int)@@ -93,7 +93,7 @@   require "value.+initialized" } -concrete Test {}+concrete Test { }  define Test {   @category process () -> (Int)@@ -131,7 +131,7 @@   require "value.+initialized" } -concrete Test {}+concrete Test { }  define Test {   @category process () -> (Int)@@ -145,7 +145,7 @@   compiles } -concrete Test {}+concrete Test { }  define Test {   @category process () -> (Int)@@ -160,7 +160,7 @@   require "value.+initialized" } -concrete Test {}+concrete Test { }  define Test {   @category process () -> (Int)@@ -185,7 +185,7 @@ }  concrete Test {-  @type get () -> (Int,Int)+  @type get () -> (Int, Int) }  define Test {@@ -220,11 +220,11 @@ }  concrete Test {-  @type get () -> (Value,Int,Int)+  @type get () -> (Value, Int, Int) }  define Test {-  get () (v,x,y) {+  get () (v, x, y) {     // This makes sure that x and y (primitive) are offset.     v <- Value.create()     x <- 1@@ -248,11 +248,11 @@ }  concrete Test {-  @type get () -> (Int,Int)+  @type get () -> (Int, Int) }  define Test {-  get () (x,y) {+  get () (x, y) {     x <- 1     y <- 2     return _@@ -261,7 +261,7 @@   testcase "positional return sets named return" {-  crash+  failure   require "message" } @@ -287,11 +287,11 @@ }  unittest withScoped {-  \ Testing.checkEquals(Test.withScoped(),"message")+  \ Testing.checkEquals(Test.withScoped(), "message") }  unittest withCleanup {-  \ Testing.checkEquals(Test.withCleanup(),"message")+  \ Testing.checkEquals(Test.withCleanup(), "message") }  concrete Test {@@ -313,7 +313,7 @@   testcase "named return not checked in condition that jumps" {-  crash+  failure   require "success" } 
tests/pointer/.zeolite-module view
@@ -1,8 +1,5 @@ root: "../.." path: "tests/pointer"-private_deps: [-  "lib/testing"-] extra_files: [   category_source {     source: "tests/pointer/Extension_Request.cpp"@@ -18,4 +15,4 @@   }   "tests/pointer/call.hpp" ]-mode: incremental {}+mode: incremental { }
tests/pointer/call.0rp view
@@ -45,6 +45,6 @@ }  concrete Service {-  @type send (Pointer<Request>,Pointer<Response>) -> ()-  @type send2 (Pointer<Message>,Pointer<Response>) -> ()+  @type send (Pointer<Request>, Pointer<Response>) -> ()+  @type send2 (Pointer<Message>, Pointer<Response>) -> () }
tests/pointer/call.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2022 Kevin P. Barry+Copyright 2022-2023 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.@@ -31,26 +31,34 @@     Response response <- Response.create("")     // This is just meant to test code generated for passing Pointer as a     // function arg or return.-    return Response.getData(callWithPointers(request.asRequest(),response.asResponse()))+    return Response.getData(callWithPointers(request.asRequest(), response.asResponse()))   }    call2 (data) {     Request request <- Request.create(data)     Response response <- Response.create("")-    \ Service.send2(request.asMessage(),response.asResponse())+    \ Service.send2(request.asMessage(), response.asResponse())     return response.formatted()   } -  @type callWithPointers (Pointer<Request>,Pointer<Response>) -> (Pointer<Response>)-  callWithPointers (request,response) {-    \ Service.send(request,response)+  @type callWithPointers (Pointer<Request>, Pointer<Response>) -> (Pointer<Response>)+  callWithPointers (request, response) {+    \ Service.send(request, response)     return response   } }  unittest test {-  \ CallHelper.call("DATA") `Testing.checkEquals` "DATA has been processed as Request"-  \ CallHelper.call2("DATA") `Testing.checkEquals` "REQUEST has been processed as Message"+  scoped {+    String value <- CallHelper.call("DATA")+  } in if (value != "DATA has been processed as Request") {+    fail(value)+  }+  scoped {+    String value <- CallHelper.call2("DATA")+  } in if (value != "REQUEST has been processed as Message") {+    fail(value)+  } }  @@ -75,23 +83,70 @@   }    call () {-    \ Request.getData(requestPointer) `Testing.checkEquals` "request"-    \ Response.getData(responsePointer) `Testing.checkEquals` "response"+    scoped {+      String value <- Request.getData(requestPointer)+    } in if (value != "request") {+      fail(value)+    }+    scoped {+      String value <- Response.getData(responsePointer)+    } in if (value != "response") {+      fail(value)+    }      Pointer<Request> localRequest <- requestPointer     Pointer<Response> localResponse <- responsePointer-    \ Request.getData(localRequest) `Testing.checkEquals` "request"-    \ Response.getData(localResponse) `Testing.checkEquals` "response"+    scoped {+      String value <- Request.getData(localRequest)+    } in if (value != "request") {+      fail(value)+    }+    scoped {+      String value <- Response.getData(localResponse)+    } in if (value != "response") {+      fail(value)+    }      localRequest <- request.asRequest()     localResponse <- response.asResponse()-    \ Request.getData(localRequest) `Testing.checkEquals` "request"-    \ Response.getData(localResponse) `Testing.checkEquals` "response"+    scoped {+      String value <- Request.getData(localRequest)+    } in if (value != "request") {+      fail(value)+    }+    scoped {+      String value <- Response.getData(localResponse)+    } in if (value != "response") {+      fail(value)+    }      requestPointer <- localRequest     responsePointer <- localResponse-    \ Request.getData(requestPointer) `Testing.checkEquals` "request"-    \ Response.getData(responsePointer) `Testing.checkEquals` "response"+    scoped {+      String value <- Request.getData(requestPointer)+    } in if (value != "request") {+      fail(value)+    }+    scoped {+      String value <- Response.getData(responsePointer)+    } in if (value != "response") {+      fail(value)+    }++    // Test swapping.+    Request request2 <- Request.create("request2")+    Pointer<Request> requestPointer2 <- request2.asRequest()+    localRequest <-> requestPointer2+    scoped {+      String value <- Request.getData(localRequest)+    } in if (value != "request2") {+      fail(value)+    }+    scoped {+      String value <- Request.getData(requestPointer2)+    } in if (value != "request") {+      fail(value)+    }   } } 
tests/positional-returns.0rt view
@@ -21,13 +21,13 @@   require "Value" } -@value interface Value {}+@value interface Value { } -concrete Test {}+concrete Test { }  define Test {   @value process () -> (Value)-  process () {}+  process () { } }  @@ -46,11 +46,11 @@ }  concrete Test {-  @type get () -> (Int,Int)+  @type get () -> (Int, Int) }  define Test {-  get () (x,y) {+  get () (x, y) {     if (false) {       x <- 1     } else {@@ -76,11 +76,11 @@ }  concrete Test {-  @type get () -> (Int,Int)+  @type get () -> (Int, Int) }  define Test {-  get () (x,y) {+  get () (x, y) {     return 1, 2   } }@@ -101,11 +101,11 @@ }  concrete Test {-  @type get () -> (Int,Int)+  @type get () -> (Int, Int) }  define Test {-  get () (x,y) {+  get () (x, y) {     y <- 2     if (false) {       x <- 1
tests/program-exit.0rt view
@@ -17,7 +17,7 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "fail builtin" {-  crash+  failure   require stderr "Failed"   require stderr "failedReturn" }@@ -80,7 +80,7 @@   testcase "exit builtin non-zero" {-  crash+  failure   // Should not output a stack trace.   exclude "exitReturn" }@@ -112,7 +112,7 @@   testcase "require empty" {-  crash+  failure   require stderr "require.+empty" } 
tests/reduce.0rt view
@@ -23,7 +23,7 @@ unittest test {   Value value <- Value.create()   scoped {-    optional Value value2 <- reduce<Value,Value>(value)+    optional Value value2 <- reduce<Value, Value>(value)   } in if (!present(value2)) {     fail("Failed")   }@@ -47,7 +47,7 @@ unittest test {   Value value <- Value.create()   scoped {-    optional String value2 <- reduce<Value,String>(value)+    optional String value2 <- reduce<Value, String>(value)   } in if (present(value2)) {     fail("Failed")   }@@ -73,7 +73,7 @@  unittest test {   Value value <- Value.create()-  optional Value value2 <- reduce<String,Value>(value)+  optional Value value2 <- reduce<String, Value>(value) }  concrete Value {@@ -96,7 +96,7 @@  unittest test {   Value value <- Value.create()-  optional Value value2 <- reduce<Value,String>(value)+  optional Value value2 <- reduce<Value, String>(value) }  concrete Value {@@ -136,11 +136,11 @@   }    attempt () {-    return reduce<Value<#x>,Value<#y>>(self)+    return reduce<Value<#x>, Value<#y>>(self)   } } -@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1@@ -173,11 +173,11 @@   }    attempt () {-    return reduce<Value<#x>,Value<#y>>(self)+    return reduce<Value<#x>, Value<#y>>(self)   } } -@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1@@ -210,11 +210,11 @@   }    attempt () {-    return reduce<Value<#x>,Value<#y>>(self)+    return reduce<Value<#x>, Value<#y>>(self)   } } -@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1@@ -247,11 +247,11 @@   }    attempt () {-    return reduce<Value<#x>,Value<#y>>(self)+    return reduce<Value<#x>, Value<#y>>(self)   } } -@value interface Type1 {}+@value interface Type1 { }  @value interface Type2 {   refines Type1@@ -263,15 +263,15 @@ }  unittest test {-  [Value1|Value2] value <- Value1.create()+  [Value1 | Value2] value <- Value1.create()   scoped {-    optional Base value2 <- reduce<[Value1|Value2],Base>(value)+    optional Base value2 <- reduce<[Value1 | Value2], Base>(value)   } in if (!present(value2)) {     fail("Failed")   } } -@value interface Base {}+@value interface Base { }  concrete Value1 {   refines Base@@ -295,15 +295,15 @@ }  unittest test {-  [Value1|Value2] value <- Value1.create()+  [Value1 | Value2] value <- Value1.create()   scoped {-    optional Value2 value2 <- reduce<[Value1|Value2],Value2>(value)+    optional Value2 value2 <- reduce<[Value1 | Value2], Value2>(value)   } in if (present(value2)) {     fail("Failed")   } } -@value interface Base {}+@value interface Base { }  concrete Value1 {   refines Base@@ -329,15 +329,15 @@ unittest test {   Value value <- Value.create()   scoped {-    optional [Base1&Base2] value2 <- reduce<Value,[Base1&Base2]>(value)+    optional [Base1 & Base2] value2 <- reduce<Value, [Base1 & Base2]>(value)   } in if (!present(value2)) {     fail("Failed")   } } -@value interface Base1 {}+@value interface Base1 { } -@value interface Base2 {}+@value interface Base2 { }  concrete Value {   refines Base1@@ -360,15 +360,15 @@ unittest test {   Value value <- Value.create()   scoped {-    optional [Base1&Base2] value2 <- reduce<Value,[Base1&Base2]>(value)+    optional [Base1 & Base2] value2 <- reduce<Value, [Base1 & Base2]>(value)   } in if (present(value2)) {     fail("Failed")   } } -@value interface Base1 {}+@value interface Base1 { } -@value interface Base2 {}+@value interface Base2 { }  concrete Value {   refines Base1@@ -388,17 +388,17 @@ }  unittest test {-  [Value1|Value2] value <- Value2.create()+  [Value1 | Value2] value <- Value2.create()   scoped {-    optional [Base1&Base2] value2 <- reduce<[Value1|Value2],[Base1&Base2]>(value)+    optional [Base1 & Base2] value2 <- reduce<[Value1 | Value2], [Base1 & Base2]>(value)   } in if (!present(value2)) {     fail("Failed")   } } -@value interface Base1 {}+@value interface Base1 { } -@value interface Base2 {}+@value interface Base2 { }  @value interface Value1 {   refines Base1@@ -424,17 +424,17 @@ }  unittest test {-  [Value1|Value2] value <- Value2.create()+  [Value1 | Value2] value <- Value2.create()   scoped {-    optional [Base1&Base2] value2 <- reduce<[Value1|Value2],[Base1&Base2]>(value)+    optional [Base1 & Base2] value2 <- reduce<[Value1 | Value2], [Base1 & Base2]>(value)   } in if (present(value2)) {     fail("Failed")   } } -@value interface Base1 {}+@value interface Base1 { } -@value interface Base2 {}+@value interface Base2 { }  @value interface Value1 {   refines Base1@@ -459,23 +459,23 @@ }  unittest test {-  [Value1&Value2] value <- Data.create()+  [Value1 & Value2] value <- Data.create()   scoped {-    optional [Base1|Base2] value2 <- reduce<[Value1&Value2],[Base1|Base2]>(value)+    optional [Base1 | Base2] value2 <- reduce<[Value1 & Value2], [Base1 | Base2]>(value)   } in if (!present(value2)) {     fail("Failed")   } } -@value interface Base1 {}+@value interface Base1 { } -@value interface Base2 {}+@value interface Base2 { }  @value interface Value1 {   refines Base1 } -@value interface Value2 {}+@value interface Value2 { }  concrete Data {   refines Value1@@ -496,21 +496,21 @@ }  unittest test {-  [Value1&Value2] value <- Data.create()+  [Value1 & Value2] value <- Data.create()   scoped {-    optional [Base1|Base2] value2 <- reduce<[Value1&Value2],[Base1|Base2]>(value)+    optional [Base1 | Base2] value2 <- reduce<[Value1 & Value2], [Base1 | Base2]>(value)   } in if (present(value2)) {     fail("Failed")   } } -@value interface Base1 {}+@value interface Base1 { } -@value interface Base2 {}+@value interface Base2 { } -@value interface Value1 {}+@value interface Value1 { } -@value interface Value2 {}+@value interface Value2 { }  concrete Data {   refines Value1@@ -533,7 +533,7 @@ unittest test {   Value<String> value <- Value<String>.create()   scoped {-    optional Value<any> value2 <- reduce<Value<String>,Value<any>>(value)+    optional Value<any> value2 <- reduce<Value<String>, Value<any>>(value)   } in if (!present(value2)) {     fail("Failed")   }@@ -557,7 +557,7 @@ unittest test {   Value<String> value <- Value<String>.create()   scoped {-    optional Value<all> value2 <- reduce<Value<String>,Value<all>>(value)+    optional Value<all> value2 <- reduce<Value<String>, Value<all>>(value)   } in if (!present(value2)) {     fail("Failed")   }@@ -581,7 +581,7 @@ unittest test {   Value<String> value <- Value<String>.create()   scoped {-    optional Value<any> value2 <- reduce<Value<String>,Value<any>>(value)+    optional Value<any> value2 <- reduce<Value<String>, Value<any>>(value)   } in if (present(value2)) {     fail("Failed")   }@@ -605,7 +605,7 @@ unittest test {   Value<all> value <- Value<all>.create()   scoped {-    optional Value<String> value2 <- reduce<Value<all>,Value<String>>(value)+    optional Value<String> value2 <- reduce<Value<all>, Value<String>>(value)   } in if (!present(value2)) {     fail("Failed")   }@@ -629,7 +629,7 @@ unittest test {   Value<any> value <- Value<any>.create()   scoped {-    optional Value<String> value2 <- reduce<Value<any>,Value<String>>(value)+    optional Value<String> value2 <- reduce<Value<any>, Value<String>>(value)   } in if (!present(value2)) {     fail("Failed")   }@@ -653,7 +653,7 @@ unittest test {   Value<all> value <- Value<all>.create()   scoped {-    optional Value<String> value2 <- reduce<Value<all>,Value<String>>(value)+    optional Value<String> value2 <- reduce<Value<all>, Value<String>>(value)   } in if (present(value2)) {     fail("Failed")   }@@ -675,7 +675,7 @@ }  unittest test {-  if (!present(reduce<Base1,Base0>(Value.create()))) {+  if (!present(reduce<Base1, Base0>(Value.create()))) {     fail("Failed")   } }@@ -704,21 +704,21 @@ }  unittest test {-  if (!present(reduce<Value,Base2<Base0>>(Value.create()))) {+  if (!present(reduce<Value, Base2<Base0>>(Value.create()))) {     fail("Failed")   }-  if (present(reduce<Value,Base2<Base1>>(Value.create()))) {+  if (present(reduce<Value, Base2<Base1>>(Value.create()))) {     fail("Failed")   } } -@value interface Base0 {}+@value interface Base0 { }  @value interface Base1 {   refines Base0 } -@value interface Base2<|#x> {}+@value interface Base2<|#x> { }  concrete Value {   refines Base2<Base0>@@ -738,9 +738,9 @@   success } -@value interface A {}-@value interface B {}-@value interface C {}+@value interface A { }+@value interface B { }+@value interface C { }  concrete AB {   refines A@@ -763,23 +763,23 @@ }  unittest leftNestedInRight {-  \ Testing.checkTrue(present(reduce<[A&B],[[A&B]|C]>(AB.create())))+  \ Testing.checkTrue(present(reduce<[A & B], [[A & B] | C]>(AB.create()))) }  unittest rightNestedInLeft {-  \ Testing.checkTrue(present(reduce<[[A|B]&C],[A|B]>(AC.create())))+  \ Testing.checkTrue(present(reduce<[[A | B] & C], [A | B]>(AC.create()))) }  unittest unionToUnion {-  \ Testing.checkTrue(present(reduce<[[A&B]|C],[[A&B]|C]>(AB.create())))+  \ Testing.checkTrue(present(reduce<[[A & B] | C], [[A & B] | C]>(AB.create()))) }  unittest intersectToIntersect {-  \ Testing.checkTrue(present(reduce<[[A|B]&C],[[A|B]&C]>(AC.create())))+  \ Testing.checkTrue(present(reduce<[[A | B] & C], [[A | B] & C]>(AC.create()))) }  unittest unionToIntersect {-  \ Testing.checkFalse(present(reduce<[A|B],[A&B]>(AB.create())))+  \ Testing.checkFalse(present(reduce<[A | B], [A & B]>(AB.create()))) }  @@ -788,13 +788,13 @@ }  unittest test {-  \ Testing.checkTrue(present(reduce<Type,Build<AsBool>>(Type.new())))-  \ Testing.checkTrue(present(reduce<Type,Build<ReadAt<Char>>>(Type.new())))-  \ Testing.checkFalse(present(reduce<Type,Build<String>>(Type.new())))+  \ Testing.checkTrue(present(reduce<Type, Build<AsBool>>(Type.new())))+  \ Testing.checkTrue(present(reduce<Type, Build<ReadAt<Char>>>(Type.new())))+  \ Testing.checkFalse(present(reduce<Type, Build<String>>(Type.new()))) }  concrete Type {-  refines Build<[AsBool&ReadAt<Char>]>+  refines Build<[AsBool & ReadAt<Char>]>    @type new () -> (Type) }@@ -810,11 +810,11 @@ }  unittest test {-  \ Testing.checkTrue(present(reduce<Type,Order<Type>>(Type.new())))-  \ Testing.checkTrue(present(reduce<Type,Order<Order<Type>>>(Type.new())))-  \ Testing.checkFalse(present(reduce<Type,Build<Type>>(Type.new())))-  \ Testing.checkTrue(present(reduce<Type,Build<Order<Type>>>(Type.new())))-  \ Testing.checkTrue(present(reduce<Type,Order<Formatted>>(Type.new())))+  \ Testing.checkTrue(present(reduce<Type, Order<Type>>(Type.new())))+  \ Testing.checkTrue(present(reduce<Type, Order<Order<Type>>>(Type.new())))+  \ Testing.checkFalse(present(reduce<Type, Build<Type>>(Type.new())))+  \ Testing.checkTrue(present(reduce<Type, Build<Order<Type>>>(Type.new())))+  \ Testing.checkTrue(present(reduce<Type, Order<Formatted>>(Type.new()))) }  concrete Type {
tests/regressions.0rt view
@@ -30,7 +30,7 @@ }  define Type1 {-  call (_) {}+  call (_) { } }  concrete Type2<#y> {@@ -82,8 +82,8 @@ }  define Child {-  call1 (_) {}-  call2 (_) {}+  call1 (_) { }+  call2 (_) { } }  @@ -139,7 +139,7 @@   }    // The count here would be 4 if scoped was prepended to cleanup.-  \ Testing.checkEquals<?>(count,3)+  \ Testing.checkEquals<?>(count, 3) }  @@ -213,8 +213,8 @@  testcase "Issue #126 is fixed" {   // https://github.com/ta0kira/zeolite/issues/126-  crash-  require "message,12345,false"+  failure+  require "message, 12345, false" }  unittest test {@@ -222,15 +222,15 @@ }  concrete Type {-  @type call () -> (String,Int,Bool)+  @type call () -> (String, Int, Bool) }  define Type {-  call () (x,y,z) {+  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())+      fail(x + ", " + y.formatted() + ", " + z.formatted())     } in return "message", 12345, false   } }@@ -259,7 +259,7 @@       if (true && message != "message") {         fail("failed")       }-    } in {}+    } in { }     return "return"   } }@@ -288,7 +288,7 @@       while (true && message != "message") {         fail("failed")       }-    } in {}+    } in { }     return "return"   } }@@ -296,7 +296,7 @@  testcase "Issue #185 is fixed" {   // https://github.com/ta0kira/zeolite/issues/185-  crash+  failure   require "message" } 
tests/scoped.0rt view
@@ -47,7 +47,7 @@   compiles } -concrete Value {}+concrete Value { }  define Value {   @value process () -> (optional Value)@@ -63,7 +63,7 @@   compiles } -concrete Value {}+concrete Value { }  define Value {   @value process () -> (optional Value)@@ -93,7 +93,7 @@   compiles } -concrete Value {}+concrete Value { }  define Value {   @value process () -> (optional Value)@@ -109,7 +109,7 @@   compiles } -concrete Value {}+concrete Value { }  define Value {   @value process () -> (optional Value)@@ -196,7 +196,7 @@   testcase "positional return sets named returns for cleanup" {-  crash+  failure   require "message"   exclude "failed" }@@ -208,11 +208,11 @@ concrete Test {   // Using a second return ensures that assignment works properly when the   // ReturnTuple is constructed during assignment.-  @type get () -> (String,Int)+  @type get () -> (String, Int) }  define Test {-  get () (value,value2) {+  get () (value, value2) {     value <- "failed"     cleanup {       fail(value)@@ -224,7 +224,7 @@   testcase "top-level assignment sets named return for cleanup" {-  crash+  failure   require "message"   exclude "failed" }@@ -252,7 +252,7 @@   require "value.+not defined" } -concrete Test {}+concrete Test { }  define Test {   @type get () -> (Int)@@ -352,8 +352,8 @@  concrete Value {   @type create () -> (Value)-  @value call () -> (Int,Int,Int)-  @value get () -> (Int,Int,Int)+  @value call () -> (Int, Int, Int)+  @value get () -> (Int, Int, Int) }  define Value {@@ -396,7 +396,7 @@     value <- 1   } in Int value <- 2 -  \ Testing.checkEquals(value,1)+  \ Testing.checkEquals(value, 1) }  @@ -409,7 +409,7 @@   scoped {   } cleanup {     value <- 1-  } in {}+  } in { }    Int value <- 2 }@@ -462,7 +462,7 @@   testcase "cleanup skipped for fail" {-  crash+  failure   require "scoped" } @@ -563,7 +563,7 @@   testcase "separate trace context for cleanup" {-  crash+  failure   require "Failed"   require "cleanup block"   require "Test\.run"@@ -610,13 +610,13 @@         }       }     }-    \ Testing.checkEquals(x,0)-    \ Testing.checkEquals(y,2)-    \ Testing.checkEquals(z,3)+    \ Testing.checkEquals(x, 0)+    \ Testing.checkEquals(y, 2)+    \ Testing.checkEquals(z, 3)   }-  \ Testing.checkEquals(x,1)-  \ Testing.checkEquals(y,2)-  \ Testing.checkEquals(z,3)+  \ Testing.checkEquals(x, 1)+  \ Testing.checkEquals(y, 2)+  \ Testing.checkEquals(z, 3) }  @@ -634,8 +634,8 @@   } in {     while ((called <- called+1) < 3) {       if (called > 1) {-        \ Testing.checkEquals(y,2)-        \ Testing.checkEquals(z,3)+        \ Testing.checkEquals(y, 2)+        \ Testing.checkEquals(z, 3)       }       cleanup {         y <- 2@@ -647,14 +647,14 @@         }       }     }-    \ Testing.checkEquals(called,3)-    \ Testing.checkEquals(x,0)-    \ Testing.checkEquals(y,2)-    \ Testing.checkEquals(z,3)+    \ Testing.checkEquals(called, 3)+    \ Testing.checkEquals(x, 0)+    \ Testing.checkEquals(y, 2)+    \ Testing.checkEquals(z, 3)   }-  \ Testing.checkEquals(x,1)-  \ Testing.checkEquals(y,2)-  \ Testing.checkEquals(z,3)+  \ Testing.checkEquals(x, 1)+  \ Testing.checkEquals(y, 2)+  \ Testing.checkEquals(z, 3) }  @@ -667,23 +667,23 @@   scoped {     Int x, Int y, Int z <- value.call()   } in {-    \ Testing.checkEquals(x,0)-    \ Testing.checkEquals(y,0)-    \ Testing.checkEquals(z,0)+    \ 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)+    \ Testing.checkEquals(x, 1)+    \ Testing.checkEquals(y, 2)+    \ Testing.checkEquals(z, 3)   } }  concrete Value {   @type create () -> (Value)-  @value call () -> (Int,Int,Int)-  @value get () -> (Int,Int,Int)+  @value call () -> (Int, Int, Int)+  @value get () -> (Int, Int, Int) }  define Value {@@ -723,7 +723,7 @@   require compiler "assign.+value" } -concrete Test {}+concrete Test { }  define Test {   @type get () -> (String)@@ -739,7 +739,7 @@   compiles } -concrete Test {}+concrete Test { }  define Test {   @type get () -> (String)@@ -756,7 +756,7 @@   require compiler "return.+cleanup" } -concrete Test {}+concrete Test { }  define Test {   @type get () -> (Int)
tests/self-offset/.zeolite-module view
@@ -1,8 +1,5 @@ root: "../.." path: "tests/self-offset"-private_deps: [-  "lib/testing"-] extra_files: [   category_source {     source: "tests/self-offset/Extension_Destructor.cpp"@@ -13,4 +10,4 @@     categories: [Offset]   } ]-mode: incremental {}+mode: incremental { }
tests/self-offset/offset.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -21,12 +21,16 @@ }  unittest test {-  \ Testing.checkEquals(Offset.new().call().get(),"different")+  scoped {+    String value <- Offset.new().call().get()+  } in if (value != "different") {+    fail(value)+  } }   testcase "VAR_SELF not allowed in destructor" {-  crash+  failure   require "VAR_SELF"   require "Destructor" }
tests/self-type.0rt view
@@ -37,7 +37,7 @@   require "#self not found" } -concrete Type {}+concrete Type { }  define Type {   @category optional #self value <- empty@@ -239,11 +239,11 @@   }    checkFrom () {-    return present(reduce<#self,#y>(self))+    return present(reduce<#self, #y>(self))   }    checkTo (from) {-    return present(reduce<#y,#self>(from))+    return present(reduce<#y, #self>(from))   } } @@ -253,7 +253,7 @@ }  unittest test {-  \ Testing.checkEquals(Type<Bool>.get(),"Type<Type<Bool>>")+  \ Testing.checkEquals(Type<Bool>.get(), "Type<Type<Bool>>") }  concrete Type<#x> {@@ -374,12 +374,12 @@  unittest withConcrete {   Type value <- Type.create()-  \ Testing.checkEquals(value.next().prev().prev().next().next().get(),1)+  \ Testing.checkEquals(value.next().prev().prev().next().next().get(), 1) }  unittest withIntersect {-  [Cell<Int>&Forward&Reverse] value <- Type.create()-  \ Testing.checkEquals(value.next().prev().prev().next().next().get(),1)+  [Cell<Int> & Forward & Reverse] value <- Type.create()+  \ Testing.checkEquals(value.next().prev().prev().next().next().get(), 1) }  @value interface Cell<|#x> {@@ -431,7 +431,7 @@  unittest test {   Type value <- Helper.new<Type>()-  \ Testing.checkEquals((value `Advance.by` 3).get(),3)+  \ Testing.checkEquals((value `Advance.by` 3).get(), 3) }  @value interface Forward {@@ -453,11 +453,11 @@ concrete Advance {   @type by<#x>     #x requires Forward-  (#x,Int) -> (#x)+  (#x, Int) -> (#x) }  define Advance {-  by (x,i) (x2) {+  by (x, i) (x2) {     x2 <- x     scoped {       Int count <- 0@@ -501,7 +501,7 @@   #x allows #self } -define Type {}+define Type { }   testcase "#self nested in param filter" {@@ -513,9 +513,9 @@   #x defines Equals<#self> } -define Type {}+define Type { } -@value interface Writer<#x|> {}+@value interface Writer<#x|> { }   testcase "#self nested in inheritance" {@@ -554,13 +554,13 @@   #x allows #self } -define Type1 {}+define Type1 { }  concrete Type2<#x> {   #x requires #self } -define Type2 {}+define Type2 { }   testcase "#self allowed in covavariant position of function param filter" {@@ -654,7 +654,7 @@   exclude "#self" } -@value interface Reader<|#x> {}+@value interface Reader<|#x> { }  concrete Type {   refines Reader<#self>@@ -675,13 +675,13 @@   require "contravariant" } -@value interface Base<#x|> {}+@value interface Base<#x|> { }  concrete Type {   refines Base<#self> } -define Type {}+define Type { }   testcase "#self cannot be contravariant in define" {@@ -691,13 +691,13 @@   require "contravariant" } -@type interface Base<#x|> {}+@type interface Base<#x|> { }  concrete Type {   defines Base<#self> } -define Type {}+define Type { }   testcase "#self cannot be invariant in refine" {@@ -707,13 +707,13 @@   require "invariant" } -@value interface Base<#x> {}+@value interface Base<#x> { }  concrete Type {   refines Base<#self> } -define Type {}+define Type { }   testcase "#self cannot be invariant in define" {@@ -723,13 +723,13 @@   require "invariant" } -@type interface Base<#x> {}+@type interface Base<#x> { }  concrete Type {   defines Base<#self> } -define Type {}+define Type { }   testcase "#self nested in value init with filters" {@@ -737,7 +737,7 @@ }  unittest test {-  \ Testing.checkEquals(Type<Int>.create().formatted(),"Type<Type<Int>>")+  \ Testing.checkEquals(Type<Int>.create().formatted(), "Type<Type<Int>>") }  concrete Type<|#x> {
tests/simple.0rt view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2020,2022 Kevin P. Barry+Copyright 2020,2022-2023 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.@@ -47,7 +47,7 @@   testcase "basic crash test" {-  crash+  failure   require stderr "testcase:"   require stderr "failure message!!!"   exclude stdout "failure message!!!"@@ -86,7 +86,7 @@ }  // The declaration for String is in scope, but it lives outside of this module.-define String {}+define String { }   testcase "attempt to define interface" {@@ -95,9 +95,9 @@   require "concrete" } -@value interface Type {}+@value interface Type { } -define Type {}+define Type { }   testcase "no deadlock with recursive type" {@@ -113,7 +113,7 @@ }  define Type {-  call () {}+  call () { } }  @@ -127,13 +127,13 @@   testcase "custom timeout works as expected" {-  crash+  failure   require "signal 14"   timeout 1 }  unittest test {-  while (true) {}+  while (true) { } }  @@ -144,4 +144,146 @@   args "\" }; exit(1); const char fake[] = { \"" } -unittest test {}+unittest test { }+++testcase "inline assignment return type" {+  success+}++unittest unboxedToUnboxed {+  Int value <- 456+  Int value2 <- (value <- 123)+  \ Testing.checkEquals(value2, 123)+  \ Testing.checkEquals(value, 123)+}++unittest unboxedToBoxed {+  optional Formatted value <- empty+  Int value2 <- (value <- 123)+  \ Testing.checkEquals(value2, 123)+  \ Testing.checkPresent(value)+  \ Testing.checkEquals(require(value).formatted(), "123")+}++unittest boxedToBoxed {+  optional Formatted value <- empty+  String value2 <- (value <- "message")+  \ Testing.checkEquals(value2, "message")+  \ Testing.checkPresent(value)+  \ Testing.checkEquals(require(value).formatted(), "message")+}+++testcase "inline assignment wrong return type" {+  error+  require "String"+  require "Int"+}++unittest test {+  optional Formatted value <- empty+  String value2 <- (value <- 123)+}+++testcase "custom testcase is started and finished" {+  failure Helper+  require "started"+  exclude "not started"+}++concrete Helper {+  defines Testcase+  @type started () -> (Bool)+}++define Helper {+  @category Bool started <- false++  started () {+    return started+  }++  start () {+    started <- true+  }++  finish () {+    if (started) {+      fail("started")+    } else {+      fail("not started")+    }+  }+}++unittest test {+  \ Testing.checkTrue(Helper.started())+}+++testcase "custom testcase is finished on exit" {+  failure Helper+  require "started"+  exclude "not started"+}++concrete Helper {+  defines Testcase+}++define Helper {+  @category Bool started <- false++  start () {+    started <- true+  }++  finish () {+    if (started) {+      fail("started")+    } else {+      fail("not started")+    }+  }+}++unittest test {+  exit(0)+}+++testcase "custom testcase is finished at most once with explicit exit" {+  success Helper+}++concrete Helper {+  defines Testcase+  @type started () -> (Bool)+}++define Helper {+  @category Bool started <- false+  @category Bool called <- false++  started () {+    return started+  }++  start () {+    started <- true+  }++  finish () {+    if (called) {+      fail("called twice")+    }+    called <- true+  }+}++unittest test {+  \ Testing.checkTrue(Helper.started())+  exit(0)+}
tests/simulate-refs/main.0rx view
@@ -47,17 +47,17 @@   @type getRoutines (ReferenceState) -> (DefaultOrder<StateMachine>)   getRoutines (state) {     return Vector<StateMachine>.new()-        .append(Routines.newShared("shared1",state))-        .append(Routines.newWeak("weak1",state))-        .append(Routines.newWeak("weak2",state))+        .append(Routines.newShared("shared1", state))+        .append(Routines.newWeak("weak1", state))+        .append(Routines.newWeak("weak2", state))   }    @type getRoutinesBroken (ReferenceState) -> (DefaultOrder<StateMachine>)   getRoutinesBroken (state) {     return Vector<StateMachine>.new()-        .append(Routines.newSharedBroken("shared1",state))-        .append(Routines.newWeakBroken("weak1",state))-        .append(Routines.newWeakBroken("weak2",state))+        .append(Routines.newSharedBroken("shared1", state))+        .append(Routines.newWeakBroken("weak1", state))+        .append(Routines.newWeakBroken("weak2", state))   }    @type runOnce (Bool) -> (Bool)@@ -69,7 +69,7 @@     } else {       routines <- getRoutines(state)     }-    \ StateExecutor:multiplexStates(routines,random)+    \ StateExecutor:multiplexStates(routines, random)      scoped {       optional String error <- state.getError()
tests/simulate-refs/ref-state.0rp view
@@ -18,16 +18,6 @@  $ModuleOnly$ -@value interface ReferenceMachine {-  immutable--  runWith (String,ReferenceState) -> (optional ReferenceMachine)-}--concrete Run {-  @type then (ReferenceMachine,ReferenceMachine) -> (ReferenceMachine)-}- concrete ReferenceState {   refines Formatted 
tests/simulate-refs/ref-state.0rx view
@@ -22,7 +22,7 @@   @value Bool locked   @value Int aliveCleanup   @value Int dataCleanup-  @value [Append<Formatted>&DefaultOrder<Formatted>] operations+  @value [Append<Formatted> & DefaultOrder<Formatted>] operations    new () {     return ReferenceState{ 0, 0, false, 0, 0, Vector<Formatted>.new() }@@ -136,36 +136,5 @@         .append(" DC: ")         .append(dataCleanup)         .build()-  }-}--define Run {-  then (first,second) {-    return RunThen.new(first,second)-  }-}--concrete RunThen {-  @type new (ReferenceMachine,ReferenceMachine) -> (ReferenceMachine)-}--define RunThen {-  refines ReferenceMachine--  @value ReferenceMachine first-  @value ReferenceMachine second--  new (first,second) {-    return RunThen{ first, second }-  }--  runWith (name,state) {-    scoped {-      optional ReferenceMachine next <- first.runWith(name,state)-    } in if (present(next)) {-      return RunThen{ require(next), second }-    } else {-      return second-    }   } }
tests/simulate-refs/routines.0rp view
@@ -19,9 +19,9 @@ $ModuleOnly$  concrete Routines {-  @type newShared (String,ReferenceState) -> (StateMachine)-  @type newWeak   (String,ReferenceState) -> (StateMachine)+  @type newShared (String, ReferenceState) -> (StateMachine)+  @type newWeak   (String, ReferenceState) -> (StateMachine) -  @type newSharedBroken (String,ReferenceState) -> (StateMachine)-  @type newWeakBroken   (String,ReferenceState) -> (StateMachine)+  @type newSharedBroken (String, ReferenceState) -> (StateMachine)+  @type newWeakBroken   (String, ReferenceState) -> (StateMachine) }
tests/simulate-refs/routines.0rx view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021-2023 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.@@ -17,86 +17,69 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define Routines {-  $ReadOnlyExcept[machine]$--  refines StateMachine--  @category ReferenceMachine dropWeak <--      IfElseDecrWeakIsZero.new(-      /*if*/   FreeRef.new(),-      /*else*/ empty)--  @category ReferenceMachine sharedThenDrop <--      LockRef.new() `Run.then`-      IfElseIncrRefIsOne.new(-      /*if*/   DecrRef.new() `Run.then`-               UnlockRef.new() `Run.then`-               dropWeak,-      /*else*/ UnlockRef.new() `Run.then`-               dropWeak `Run.then`-               dropShared)+  @category optional StateTransition<String, ReferenceState> dropWeak <-+      Run:ifElse(+      test:   DecrWeakIsZero.new(),+      doIf:   FreeRef.new(),+      doElse: empty) -  @category ReferenceMachine dropShared <--      LockRef.new() `Run.then`-      IfElseDecrRefIsZero.new(-      /*if*/   FreeObject.new() `Run.then`-               UnlockRef.new() `Run.then`-               IfElseDecrWeakIsZero.new(-               /*if*/   FreeRef.new(),-               /*else*/ empty),-      /*else*/ UnlockRef.new())+  @category optional StateTransition<String, ReferenceState> sharedThenDrop <-+      LockRef.new() `Run:then`+      Run:ifElse(+      test:   IncrRefIsOne.new(),+      doIf:   DecrRef.new() `Run:then`+              UnlockRef.new() `Run:then`+              dropWeak,+      doElse: UnlockRef.new() `Run:then`+              dropWeak `Run:then`+              dropShared) -  @category ReferenceMachine sharedThenDropBroken <--      IfElsePlusLockModLockZero.new(-      /*if*/   MinusLock.new() `Run.then`-               dropWeak,-      /*else*/ MinusLockPlusOne.new() `Run.then`-               dropWeak `Run.then`-               dropSharedBroken)+  @category optional StateTransition<String, ReferenceState> dropShared <-+      LockRef.new() `Run:then`+      Run:ifElse(+      test:   DecrRefIsZero.new(),+      doIf:   FreeObject.new() `Run:then`+              UnlockRef.new() `Run:then`+              dropWeak,+      doElse: UnlockRef.new()) -  @category ReferenceMachine dropSharedBroken <--      IfElseDecrRefIsZero.new(-      /*if*/   FreeObject.new() `Run.then`-               IfElseDecrWeakIsZero.new(-               /*if*/   FreeRef.new(),-               /*else*/ empty),-      /*else*/ empty)+  @category optional StateTransition<String, ReferenceState> sharedThenDropBroken <-+      Run:ifElse(+      test:   PlusLockModLockZero.new(),+      doIf:   MinusLock.new() `Run:then`+              dropWeak,+      doElse: MinusLockPlusOne.new() `Run:then`+              dropWeak `Run:then`+              dropSharedBroken) -  @value String name-  @value ReferenceState state-  @value optional ReferenceMachine machine+  @category optional StateTransition<String, ReferenceState> dropSharedBroken <-+      Run:ifElse(+      test:   DecrRefIsZero.new(),+      doIf:   FreeObject.new() `Run:then`+              dropWeak,+      doElse: empty) -  newShared (name,state) {+  newShared (name, state) {     if (state.addStrong() == 1) {       \ state.addWeak()     }-    return #self{ name, state, dropShared }+    return LabeledStateMachine:new(name, state, dropShared)   } -  newWeak (name,state) {+  newWeak (name, state) {     \ state.addWeak()-    return #self{ name, state, sharedThenDrop }+    return LabeledStateMachine:new(name, state, sharedThenDrop)   } -  newSharedBroken (name,state) {+  newSharedBroken (name, state) {     if (state.addStrong() == 1) {       \ state.addWeak()     }-    return #self{ name, state, dropSharedBroken }+    return LabeledStateMachine:new(name, state, dropSharedBroken)   } -  newWeakBroken (name,state) {+  newWeakBroken (name, state) {     \ state.addWeak()-    return #self{ name, state, sharedThenDropBroken }-  }--  transition () {-    if (!present(machine)) {-      return empty-    } elif (present((machine <- require(machine).runWith(name,state)))) {-      return self-    } else {-      return empty-    }+    return LabeledStateMachine:new(name, state, sharedThenDropBroken)   } }
tests/simulate-refs/state.0rp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -22,6 +22,38 @@   transition () -> (optional StateMachine) } +@value interface StateTransition<#l, #s|> {+  immutable++  runWith (#l, #s) -> (optional StateTransition<#l, #s>)+}++@value interface StatePredicate<#l, #s|> {+  immutable++  test (#l, #s) -> (Bool)+}++concrete Run {+  @category then<#l, #s>+  (optional StateTransition<#l, #s>, optional StateTransition<#l, #s>) ->+  (optional StateTransition<#l, #s>)++  @category ifElse<#l, #s>+  (StatePredicate<#l, #s> test:,+   optional StateTransition<#l, #s> doIf:,+   optional StateTransition<#l, #s> doElse:) ->+  (StateTransition<#l, #s>)+}++concrete LabeledStateMachine<#l, #s> {+  #l immutable++  @category new<#l, #s>+    #l immutable+  (#l, #s, optional StateTransition<#l, #s>) -> (StateMachine)+}+ concrete StateExecutor {-  @category multiplexStates (DefaultOrder<StateMachine>,Generator<Float>) -> ()+  @category multiplexStates (DefaultOrder<StateMachine>, Generator<Float>) -> () }
tests/simulate-refs/state.0rx view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021-2023 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.@@ -16,16 +16,107 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] +define Run {+  then (first, second) {+    return delegate -> `RunThen:new`+  }++  ifElse (test, doIf, doElse) {+    return delegate -> `RunIfElse:new`+  }+}++concrete RunThen<#l, #s|> {+  @category new<#l, #s> (optional StateTransition<#l, #s>, optional StateTransition<#l, #s>) -> (optional StateTransition<#l, #s>)+}++define RunThen {+  refines StateTransition<#l, #s>++  @value StateTransition<#l, #s> first+  @value StateTransition<#l, #s> second++  new (first, second) {+    if (! `present` first) {+      return second+    } elif (! `present` second) {+      return first+    } else {+      return RunThen<#l, #s>{ `require` first, `require` second }+    }+  }++  runWith (label, state) {+    scoped {+      optional StateTransition<#l, #s> next <- label `first.runWith` state+    } in if (`present` next) {+      return #self{ `require` next, second }+    } else {+      return second+    }+  }+}++concrete RunIfElse<#l, #s|> {+  @category new<#l, #s>+  (StatePredicate<#l, #s> test:, optional StateTransition<#l, #s> doIf:, optional StateTransition<#l, #s> doElse:) ->+  (StateTransition<#l, #s>)+}++define RunIfElse {+  refines StateTransition<#l, #s>++  @value StatePredicate<#l, #s> test+  @value optional StateTransition<#l, #s> doIf+  @value optional StateTransition<#l, #s> doElse++  new (test, doIf, doElse) {+    return delegate -> RunIfElse<#l, #s>+  }++  runWith (label, state) {+    if (label `test.test` state) {+      return doIf+    } else {+      return doElse+    }+  }+}++define LabeledStateMachine {+  $ReadOnlyExcept[machine]$++  refines StateMachine++  @value #l label+  @value #s state+  @value optional StateTransition<#l, #s> machine++  new (label, state, transition) {+    return delegate -> LabeledStateMachine<#l, #s>+  }++  transition () {+    if (!present(machine)) {+      return empty+    } elif (`present` (machine <- label `require(machine).runWith` state)) {+      return self+    } else {+      return empty+    }+  }+}+ define StateExecutor {-  multiplexStates (original,random) {-    HashedMap<Int,StateMachine> states <- HashedMap<Int,StateMachine>.new()+  multiplexStates (original, random) {+    HashedMap<Int, StateMachine> states <- HashedMap<Int, StateMachine>.new()     CategoricalTree<Int> weights <- CategoricalTree<Int>.new()      scoped {       Int index <- 0     } in traverse (original.defaultOrder() -> StateMachine state) {-      \ states.set(index,state)-      \ weights.setWeight(index,1)+      \ index `states.set` state+      \ index `weights.setWeight` 1     } update {       index <- index+1     }@@ -35,11 +126,11 @@       Int index <- weights.locate((random.generate()*weights.getTotal().asFloat()).asInt())       scoped {         optional StateMachine newState <- require(states.get(index)).transition()-      } in if (present(newState)) {-        \ states.set(index,require(newState))+      } in if (`present` newState) {+        \ index `states.set` `require` newState       } else {-        \ states.remove(index)-        \ weights.setWeight(index,0)+        \ `states.remove` index+        \ index `weights.setWeight` 0       }     }   }
tests/simulate-refs/transitions.0rp view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -19,49 +19,49 @@ $ModuleOnly$  concrete LockRef {-  @type new () -> (ReferenceMachine)+  @type new () -> (StateTransition<String, ReferenceState>) } -concrete IfElseDecrRefIsZero {-  @type new (optional ReferenceMachine,optional ReferenceMachine) -> (ReferenceMachine)+concrete DecrRefIsZero {+  @type new () -> (StatePredicate<String, ReferenceState>) }  concrete UnlockRef {-  @type new () -> (ReferenceMachine)+  @type new () -> (StateTransition<String, ReferenceState>) }  concrete FreeObject {-  @type new () -> (ReferenceMachine)+  @type new () -> (StateTransition<String, ReferenceState>) } -concrete IfElseDecrWeakIsZero {-  @type new (optional ReferenceMachine,optional ReferenceMachine) -> (ReferenceMachine)+concrete DecrWeakIsZero {+  @type new () -> (StatePredicate<String, ReferenceState>) }  concrete FreeRef {-  @type new () -> (ReferenceMachine)+  @type new () -> (StateTransition<String, ReferenceState>) } -concrete IfElseIncrRefIsOne {-  @type new (optional ReferenceMachine,optional ReferenceMachine) -> (ReferenceMachine)+concrete IncrRefIsOne {+  @type new () -> (StatePredicate<String, ReferenceState>) }  concrete DecrRef {-  @type new () -> (ReferenceMachine)+  @type new () -> (StateTransition<String, ReferenceState>) }  concrete DecrWeak {-  @type new () -> (ReferenceMachine)+  @type new () -> (StateTransition<String, ReferenceState>) } -concrete IfElsePlusLockModLockZero {-  @type new (optional ReferenceMachine,optional ReferenceMachine) -> (ReferenceMachine)+concrete PlusLockModLockZero {+  @type new () -> (StatePredicate<String, ReferenceState>) }  concrete MinusLockPlusOne {-  @type new () -> (ReferenceMachine)+  @type new () -> (StateTransition<String, ReferenceState>) }  concrete MinusLock {-  @type new () -> (ReferenceMachine)+  @type new () -> (StateTransition<String, ReferenceState>) }
tests/simulate-refs/transitions.0rx view
@@ -1,5 +1,5 @@ /* ------------------------------------------------------------------------------Copyright 2021 Kevin P. Barry+Copyright 2021,2023 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.@@ -17,11 +17,11 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  define LockRef {-  refines ReferenceMachine+  refines StateTransition<String, ReferenceState>    new () { return #self{ } } -  runWith (name,state) {+  runWith (name, state) {     \ state.addOperation<#self>(name)     if (state.tryLock()) {       return empty@@ -31,30 +31,23 @@   } } -define IfElseDecrRefIsZero {-  refines ReferenceMachine--  @value optional ReferenceMachine doIf-  @value optional ReferenceMachine doElse+define DecrRefIsZero {+  refines StatePredicate<String, ReferenceState> -  new (doIf,doElse) { return #self{ doIf, doElse } }+  new () { return #self{ } } -  runWith (name,state) {+  test (name, state) {     \ state.addOperation<#self>(name)-    if (state.remStrong() == 0) {-      return doIf-    } else {-      return doElse-    }+    return state.remStrong() == 0   } }  define UnlockRef {-  refines ReferenceMachine+  refines StateTransition<String, ReferenceState>    new () { return #self{ } } -  runWith (name,state) {+  runWith (name, state) {     \ state.addOperation<#self>(name)     \ state.remLock()     return empty@@ -62,71 +55,57 @@ }  define FreeObject {-  refines ReferenceMachine+  refines StateTransition<String, ReferenceState>    new () { return #self{ } } -  runWith (name,state) {+  runWith (name, state) {     \ state.addOperation<#self>(name)     \ state.kill()     return empty   } } -define IfElseDecrWeakIsZero {-  refines ReferenceMachine--  @value optional ReferenceMachine doIf-  @value optional ReferenceMachine doElse+define DecrWeakIsZero {+  refines StatePredicate<String, ReferenceState> -  new (doIf,doElse) { return #self{ doIf, doElse } }+  new () { return #self{ } } -  runWith (name,state) {+  test (name, state) {     \ state.addOperation<#self>(name)-    if (state.remWeak() == 0) {-      return doIf-    } else {-      return doElse-    }+    return state.remWeak() == 0   } }  define FreeRef {-  refines ReferenceMachine+  refines StateTransition<String, ReferenceState>    new () { return #self{ } } -  runWith (name,state) {+  runWith (name, state) {     \ state.addOperation<#self>(name)     \ state.freeData()     return empty   } } -define IfElseIncrRefIsOne {-  refines ReferenceMachine--  @value optional ReferenceMachine doIf-  @value optional ReferenceMachine doElse+define IncrRefIsOne {+  refines StatePredicate<String, ReferenceState> -  new (doIf,doElse) { return #self{ doIf, doElse } }+  new () { return #self{ } } -  runWith (name,state) {+  test (name, state) {     \ state.addOperation<#self>(name)-    if (state.addStrong() == 1) {-      return doIf-    } else {-      return doElse-    }+    return state.addStrong() == 1   } }  define DecrRef {-  refines ReferenceMachine+  refines StateTransition<String, ReferenceState>    new () { return #self{ } } -  runWith (name,state) {+  runWith (name, state) {     \ state.addOperation<#self>(name)     \ state.remStrong()     return empty@@ -134,41 +113,34 @@ }  define DecrWeak {-  refines ReferenceMachine+  refines StateTransition<String, ReferenceState>    new () { return #self{ } } -  runWith (name,state) {+  runWith (name, state) {     \ state.addOperation<#self>(name)     \ state.remWeak()     return empty   } } -define IfElsePlusLockModLockZero {-  refines ReferenceMachine--  @value optional ReferenceMachine doIf-  @value optional ReferenceMachine doElse+define PlusLockModLockZero {+  refines StatePredicate<String, ReferenceState> -  new (doIf,doElse) { return #self{ doIf, doElse } }+  new () { return #self{ } } -  runWith (name,state) {+  test (name, state) {     \ state.addOperation<#self>(name)-    if (state.plusStrong($ExprLookup[LOCK_VAL]$) % $ExprLookup[LOCK_VAL]$ == 0) {-      return doIf-    } else {-      return doElse-    }+    return state.plusStrong($ExprLookup[LOCK_VAL]$) % $ExprLookup[LOCK_VAL]$ == 0   } }  define MinusLockPlusOne {-  refines ReferenceMachine+  refines StateTransition<String, ReferenceState>    new () { return #self{ } } -  runWith (name,state) {+  runWith (name, state) {     \ state.addOperation<#self>(name)     \ state.minusStrong($ExprLookup[LOCK_VAL]$-1)     return empty@@ -176,11 +148,11 @@ }  define MinusLock {-  refines ReferenceMachine+  refines StateTransition<String, ReferenceState>    new () { return #self{ } } -  runWith (name,state) {+  runWith (name, state) {     \ state.addOperation<#self>(name)     \ state.minusStrong($ExprLookup[LOCK_VAL]$)     return empty
+ tests/swap.0rt view
@@ -0,0 +1,367 @@+/* -----------------------------------------------------------------------------+Copyright 2022-2023 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 "successful swaps" {+  success+}++concrete Test {+  @type new () -> (#self)+  @value testUnboxedCategoryValue () -> ()+  @value testBoxedCategoryValue () -> ()+  @value testWeakCategoryValue () -> ()+  @value testCategorySame () -> ()+  @value testUnboxedValueSame () -> ()+  @value testBoxedValueSame () -> ()+  @value testUnboxedNamedReturn () -> ()+  @value testBoxedNamedReturn () -> ()+}++define Test {+  @category Int         unboxedCategory <- 123+  @category String      boxedCategory   <- "abc"+  @category weak String weakCategory    <- boxedCategory++  @value Int         unboxedValue+  @value String      boxedValue+  @value weak String weakValue++  new () {+    String value <- "def"+    return #self{ 456, value, value }+  }++  testUnboxedCategoryValue () {+    unboxedCategory <-> unboxedValue+    \ Testing.checkEquals(unboxedCategory, 456)+    \ Testing.checkEquals(unboxedValue, 123)+    unboxedValue <-> unboxedCategory+    \ Testing.checkEquals(unboxedCategory, 123)+    \ Testing.checkEquals(unboxedValue, 456)+  }++  testBoxedCategoryValue () {+    boxedCategory <-> boxedValue+    \ Testing.checkEquals(boxedCategory, "def")+    \ Testing.checkEquals(boxedValue, "abc")+    boxedValue <-> boxedCategory+    \ Testing.checkEquals(boxedCategory, "abc")+    \ Testing.checkEquals(boxedValue, "def")+  }++  testWeakCategoryValue () {+    weakCategory <-> weakValue+    \ Testing.checkEquals(`strong` weakCategory, "def")+    \ Testing.checkEquals(`strong` weakValue, "abc")+    weakValue <-> weakCategory+    \ Testing.checkEquals(`strong` weakCategory, "abc")+    \ Testing.checkEquals(`strong` weakValue, "def")+  }++  testCategorySame () {+    boxedCategory <-> boxedCategory+    \ Testing.checkEquals(boxedCategory, "abc")+  }++  testUnboxedValueSame () {+    unboxedValue <-> unboxedValue+    \ Testing.checkEquals(unboxedValue, 456)+  }++  testBoxedValueSame () {+    boxedValue <-> boxedValue+    \ Testing.checkEquals(boxedValue, "def")+  }++  testUnboxedNamedReturn () {+    \ Testing.checkEquals(callWithNamedUnboxed(), 456)+  }++  testBoxedNamedReturn () {+    \ Testing.checkEquals(callWithNamedBoxed(), "def")+  }++  @value callWithNamedUnboxed () -> (Int)+  callWithNamedUnboxed () (value1) {+    value1     <- 123+    Int value2 <- 456+    value1 <-> value2+    \ Testing.checkEquals(value1, 456)+    \ Testing.checkEquals(value2, 123)+  }++  @value callWithNamedBoxed () -> (String)+  callWithNamedBoxed () (value1) {+    value1        <- "abc"+    String value2 <- "def"+    value1 <-> value2+    \ Testing.checkEquals(value1, "def")+    \ Testing.checkEquals(value2, "abc")+  }+}++unittest testUnboxedCategoryValue {+  \ Test.new().testUnboxedCategoryValue()+}++unittest testBoxedCategoryValue {+  \ Test.new().testBoxedCategoryValue()+}++unittest testWeakCategoryValue {+  \ Test.new().testWeakCategoryValue()+}++unittest testCategorySame {+  \ Test.new().testCategorySame()+}++unittest testUnboxedValueSame {+  \ Test.new().testUnboxedValueSame()+}++unittest testBoxedValueSame {+  \ Test.new().testBoxedValueSame()+}++unittest testUnboxedNamedReturn {+  \ Test.new().testUnboxedNamedReturn()+}++unittest testBoxedNamedReturn {+  \ Test.new().testBoxedNamedReturn()+}++unittest testUnboxedLocal {+  Int value1 <- 123+  Int value2 <- 456+  value1 <-> value2+  \ Testing.checkEquals(value1, 456)+  \ Testing.checkEquals(value2, 123)+}++unittest testBoxedLocal {+  String value1 <- "abc"+  String value2 <- "def"+  value1 <-> value2+  \ Testing.checkEquals(value1, "def")+  \ Testing.checkEquals(value2, "abc")+}++unittest testOptionalLocal {+  optional String value1 <- "abc"+  optional String value2 <- "def"+  value1 <-> value2+  \ Testing.checkEquals(value1, "def")+  \ Testing.checkEquals(value2, "abc")+}++unittest testWeakLocal {+  optional String source1 <- "abc"+  optional String source2 <- "def"+  weak String value1 <- source1+  weak String value2 <- source2+  $Hidden[source1, source2]$+  value1 <-> value2+  \ Testing.checkEquals(`strong` value1, "def")+  \ Testing.checkEquals(`strong` value2, "abc")+}++unittest testUnboxedTopLevelScoped {+  Int value1 <- 123+  scoped {+    Int value2 <- 456+  } cleanup {+    \ Testing.checkEquals(value1, 456)+  } in value1 <-> value2+  \ Testing.checkEquals(value1, 456)+}++unittest testBoxedTopLevelScoped {+  String value1 <- "abc"+  weak String reference <- value1+  scoped {+    String value2 <- "def"+  } cleanup {+    \ Testing.checkEquals(value1, "def")+    \ Testing.checkEquals(value2, "abc")+    \ Testing.checkEquals(`strong` reference, "abc")+  } in value1 <-> value2+  \ Testing.checkEquals(value1, "def")+  // value2 is out of scope now.+  \ Testing.checkEmpty(`strong` reference)+}+++testcase "swap works with parameters" {+  success+}++concrete Test<#x> {+  #x requires Formatted+  #x defines Equals<#x>++  @type new (#x) -> (#self)+  @value testSwap (#x) -> ()+}++define Test {+  @value #x value++  new (value) { return #self{ value } }++  testSwap (value2) {+    // value2 is read-only because it's an argument.+    #x temp <- value2+    value <-> temp+  \ Testing.checkEquals(value, value2)+  }+}++unittest testUnboxed {+  \ Test<Int>.new(123).testSwap(456)+}++unittest testBxed {+  \ Test<String>.new("abc").testSwap("def")+}+++testcase "swap not allowed with incompatible types" {+  error+  require "Int"+  require "String"+}++unittest test {+  Int    value1 <- 123+  String value2 <- "abc"+  value1 <-> value2+}+++testcase "swap not allowed with invalid left assignment" {+  error+  require "modifier"+}++unittest test {+  Int          value1 <- 123+  optional Int value2 <- empty+  value1 <-> value2+}+++testcase "swap not allowed with invalid right assignment" {+  error+  require "modifier"+}++unittest test {+  optional Int value1 <- empty+  Int          value2 <- 456+  value1 <-> value2+}+++testcase "swap not allowed with read-only left" {+  error+  require "value1"+  require "read-only"+  exclude "value2"+}++unittest test {+  Int value1 <- 1+  Int value2 <- 2+  $ReadOnly[value1]$+  value1 <-> value2+}+++testcase "swap not allowed with read-only right" {+  error+  require "value2"+  require "read-only"+  exclude "value1"+}++unittest test {+  Int value1 <- 1+  Int value2 <- 2+  $ReadOnly[value2]$+  value1 <-> value2+}+++testcase "swap not allowed with hidden left" {+  error+  require "value1"+  require "hidden"+  exclude "value2"+}++unittest test {+  Int value1 <- 1+  Int value2 <- 2+  $Hidden[value1]$+  value1 <-> value2+}+++testcase "swap not allowed with hidden right" {+  error+  require "value2"+  require "hidden"+  exclude "value1"+}++unittest test {+  Int value1 <- 1+  Int value2 <- 2+  $Hidden[value2]$+  value1 <-> value2+}+++testcase "swap not allowed with deferred left" {+  error+  require "value1"+  require "initialized"+  exclude "value2"+}++unittest test {+  Int value1 <- defer+  Int value2 <- 2+  value1 <-> value2+}+++testcase "swap not allowed with deferred right" {+  error+  require "value2"+  require "initialized"+  exclude "value1"+}++unittest test {+  Int value1 <- 1+  Int value2 <- defer+  value1 <-> value2+}
tests/templates/.zeolite-module view
@@ -10,4 +10,4 @@     categories: [Templated2]   } ]-mode: incremental {}+mode: incremental { }
tests/templates/tests.0rt view
@@ -17,7 +17,7 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "template compiles to binary" {-  crash+  failure   require "Templated:create is not implemented" } @@ -27,7 +27,7 @@   testcase "private template generated" {-  crash+  failure   require "Templated2\.create is not implemented" } 
+ tests/test-helpers.0rp view
@@ -0,0 +1,113 @@+/* -----------------------------------------------------------------------------+Copyright 2020-2021,2023 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]++$ModuleOnly$+$TestsOnly$++// General helpers for use in unit tests.+concrete Testing {+  // Check the values for equality. Crashes if they are not equal.+  //+  // Args:+  // - #x: Actual value.+  // - #x: Expected value.+  @type checkEquals<#x>+    #x defines Equals<#x>+  (optional #x, optional #x) -> ()++  // Check the values for inequality. Crashes if they are equal.+  //+  // Args:+  // - #x: Actual value.+  // - #x: Expected value.+  @type checkNotEquals<#x>+    #x defines Equals<#x>+  (optional #x, optional #x) -> ()++  // Check the value for empty. Crashes if present.+  //+  // Args:+  // - #x: Actual value.+  @type checkEmpty<#x> (optional #x) -> ()++  // Check the value for present. Crashes if empty.+  //+  // Args:+  // - optional any: Actual value.+  @type checkPresent (optional any) -> ()++  // Check the value for true. Crashes if false.+  //+  // Args:+  // - AsBool: Actual value.+  @type checkTrue (optional AsBool) -> ()++  // Check the value for false. Crashes if true.+  //+  // Args:+  // - AsBool: Actual value.+  @type checkFalse (optional AsBool) -> ()++  // Check that the value is within a range. Crashes if it is not in the range.+  //+  // Args:+  // - #x: Actual value.+  // - #x: Lower bound.+  // - #x: Upper bound.+  //+  // Notes:+  // - This could be done without Equals, except that some types have+  //   "undefined" values (e.g., NaN, for Float) that prevent inferring equality+  //   from less-than comparisons.+  @type checkBetween<#x>+    #x defines Equals<#x>+    #x defines LessThan<#x>+  (optional #x, #x, #x) -> ()++  // Check that the value is above the limit. Crashes if it is not in the range.+  //+  // Args:+  // - #x: Actual value.+  // - #x: Lower bound.+  //+  // Notes:+  // - This could be done without Equals, except that some types have+  //   "undefined" values (e.g., NaN, for Float) that prevent inferring equality+  //   from less-than comparisons.+  // - This comparison doesn't allow the value to equal the bound.+  @type checkGreaterThan<#x>+    #x defines Equals<#x>+    #x defines LessThan<#x>+  (optional #x, #x) -> ()++  // Check that the value is below the limit. Crashes if it is not in the range.+  //+  // Args:+  // - #x: Actual value.+  // - #x: Upper bound.+  //+  // Notes:+  // - This could be done without Equals, except that some types have+  //   "undefined" values (e.g., NaN, for Float) that prevent inferring equality+  //   from less-than comparisons.+  // - This comparison doesn't allow the value to equal the bound.+  @type checkLessThan<#x>+    #x defines Equals<#x>+    #x defines LessThan<#x>+  (optional #x, #x) -> ()+}
+ tests/test-helpers.0rt view
@@ -0,0 +1,300 @@+/* -----------------------------------------------------------------------------+Copyright 2020-2021,2023 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)+  \ Testing.checkEquals<Int>(empty, empty)+}+++testcase "checkEquals fail non-empty" {+  failure+  require stderr "13"+  require stderr "15"+}++unittest test {+  \ Testing.checkEquals(13, 15)+}+++testcase "checkEquals fail empty" {+  failure+  require stderr "13"+  require stderr "empty"+}++unittest test {+  \ Testing.checkEquals(13, empty)+}+++testcase "checkNotEquals success" {+  success+}++unittest test {+  \ Testing.checkNotEquals(12, 13)+  \ Testing.checkNotEquals(empty, 13)+  \ Testing.checkNotEquals(12, empty)+}+++testcase "checkNotEquals fail non-empty" {+  failure+  require stderr "13.*13"+}++unittest test {+  \ Testing.checkNotEquals(13, 13)+}+++testcase "checkNotEquals fail empty" {+  failure+  require stderr "empty.*empty"+}++unittest test {+  \ Testing.checkNotEquals<Int>(empty, empty)+}+++testcase "checkEmpty success" {+  success+}++unittest formatted {+  \ Testing.checkEmpty(empty)+}++unittest notFormatted {+  optional CharBuffer value <- empty+  \ Testing.checkEmpty(value)+}+++testcase "checkEmpty fail formatted" {+  failure+  require stderr "13"+  require stderr "empty"+}++unittest test {+  \ Testing.checkEmpty(13)+}+++testcase "checkEmpty fail unformatted" {+  failure+  require stderr "unknown"+  require stderr "empty"+}++unittest test {+  CharBuffer value <- CharBuffer.new(10)+  \ Testing.checkEmpty(value)+}+++testcase "checkPresent success" {+  success+}++unittest test {+  \ Testing.checkPresent(13)+}+++testcase "checkPresent fail" {+  failure+  require stderr "empty"+}++unittest test {+  \ Testing.checkPresent(empty)+}+++testcase "checkBetween success" {+  success+}++unittest test {+  \ Testing.checkBetween(13, 13, 15)+}+++testcase "checkBetween fail non-empty" {+  failure+  require stderr "13"+  require stderr "14"+  require stderr "15"+}++unittest test {+  \ Testing.checkBetween(13, 14, 15)+}+++testcase "checkBetween fail empty" {+  failure+  require stderr "empty"+  require stderr "14"+  require stderr "15"+}++unittest test {+  \ Testing.checkBetween(empty, 14, 15)+}+++testcase "checkBetween bad range" {+  failure+  exclude stderr "14"+  require stderr "13"+  require stderr "15"+}++unittest test {+  \ Testing.checkBetween(14, 15, 13)+}+++testcase "checkGreaterThan success" {+  success+}++unittest test {+  \ Testing.checkGreaterThan(13, 11)+}+++testcase "checkGreaterThan fail non-empty" {+  failure+  require stderr "13"+  require stderr "14"+}++unittest test {+  \ Testing.checkGreaterThan(13, 14)+}+++testcase "checkGreaterThan fail empty" {+  failure+  require stderr "empty"+  require stderr "14"+}++unittest test {+  \ Testing.checkGreaterThan(empty, 14)+}+++testcase "checkLessThan success" {+  success+}++unittest test {+  \ Testing.checkLessThan(13, 14)+}+++testcase "checkLessThan fail non-empty" {+  failure+  require stderr "13"+  require stderr "11"+}++unittest test {+  \ Testing.checkLessThan(13, 11)+}+++testcase "checkLessThan fail empty" {+  failure+  require stderr "empty"+  require stderr "11"+}++unittest test {+  \ Testing.checkLessThan(empty, 11)+}+++testcase "checkTrue success" {+  success+}++unittest test {+  \ Testing.checkTrue(1)+}+++testcase "checkTrue fail non-empty" {+  failure+  require stderr "true"+}++unittest test {+  \ Testing.checkTrue(0)+}+++testcase "checkTrue fail empty" {+  failure+  require stderr "true"+}++unittest test {+  \ Testing.checkTrue(empty)+}+++testcase "checkFalse success" {+  success+}++unittest test {+  \ Testing.checkFalse(0)+}+++testcase "checkFalse fail non-empty" {+  failure+  require stderr "false"+}++unittest test {+  \ Testing.checkFalse(1)+}+++testcase "checkFalse fail empty" {+  failure+  require stderr "false"+}++unittest test {+  \ Testing.checkFalse(empty)+}
+ tests/test-helpers.0rx view
@@ -0,0 +1,169 @@+/* -----------------------------------------------------------------------------+Copyright 2020-2021,2023 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) { $NoTrace$+    Bool failed <- false+    if (`present` x && `present` y && !#x.equals(`require` x, `require` y)) {+      failed <- true+    } elif (`present` x != `present` y) {+      failed <- true+    }+    if (failed) {+      fail(String.builder()+          .append(autoFormat(x))+          .append(" is not equal to ")+          .append(autoFormat(y))+          .build())+    }+  }++  checkNotEquals (x, y) { $NoTrace$+    Bool failed <- false+    if (`present` x && `present` y && #x.equals(`require` x, `require` y)) {+      failed <- true+    } elif (! `present` x &&  ! `present` y) {+      failed <- true+    }+    if (failed) {+      fail(String.builder()+          .append(autoFormat(x))+          .append(" is equal to ")+          .append(autoFormat(y))+          .build())+    }+  }++  checkEmpty (x) { $NoTrace$+    if (present(x)) {+      fail(String.builder()+          .append(autoFormat(x))+          .append(" is not empty")+          .build())+    }+  }++  checkPresent (x) { $NoTrace$+    if (!present(x)) {+      fail(String.builder()+          .append("expected non-empty value")+          .build())+    }+  }++  checkTrue (x) { $NoTrace$+    if (! `present` x) {+      fail("expected true but got empty")+    }+    if (!require(x).asBool()) {+      fail("expected true but got false")+    }+  }++  checkFalse (x) { $NoTrace$+    if (! `present` x) {+      fail("expected false but got empty")+    }+    if (require(x).asBool()) {+      fail("expected false but got true")+    }+  }++  checkBetween (x, l, h) { $NoTrace$+    if (!lessEquals(l, h)) {+      fail(String.builder()+          .append("Upper limit ")+          .append(autoFormat(l))+          .append(" is not at or above lower limit ")+          .append(autoFormat(h))+          .build())+    }+    Bool failed <- false+    if (! `present` x) {+      failed <- true+    } elif (!lessEquals(l, `require` x) || !lessEquals(`require` x, h)) {+      failed <- true+    }+    if (failed) {+      fail(String.builder()+          .append(autoFormat(x))+          .append(" is not between ")+          .append(autoFormat(l))+          .append(" and ")+          .append(autoFormat(h))+          .build())+    }+  }++  checkGreaterThan (x, l) { $NoTrace$+    Bool failed <- false+    if (! `present` x) {+      failed <- true+    } elif (!lessEquals(l, `require` x)) {+      failed <- true+    }+    if (failed) {+      fail(String.builder()+          .append(autoFormat(x))+          .append(" is not greater than ")+          .append(autoFormat(l))+          .build())+    }+  }++  checkLessThan (x, h) { $NoTrace$+    Bool failed <- false+    if (! `present` x) {+      failed <- true+    } elif (!lessEquals(`require` x, h)) {+      failed <- true+    }+    if (failed) {+      fail(String.builder()+          .append(autoFormat(x))+          .append(" is not less than ")+          .append(autoFormat(h))+          .build())+    }+  }++  @type autoFormat<#x> (optional #x) -> (Formatted)+  autoFormat (x) {+    if (! `present` x) {+      return "empty"+    }+    scoped {+      optional Formatted formatted <- reduce<#x, Formatted>(x)+    } in if (`present` formatted) {+      return `require` formatted+    } else {+      return "(unknown)"+    }+  }++  @type lessEquals<#x>+    #x defines Equals<#x>+    #x defines LessThan<#x>+  (#x, #x) -> (Bool)+  lessEquals (x, y) { $NoTrace$+    // Using !#x.lessThan(y, x) wouldn't account for NaNs.+    return #x.lessThan(x, y) || #x.equals(x, y)+  }+}
tests/tests-only/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../.." path: "tests/tests-only"-mode: incremental {}+mode: incremental { }
tests/tests-only/private.0rx view
@@ -16,6 +16,6 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -define Type1 {}+define Type1 { } -define Type2 {}+define Type2 { }
tests/tests-only/public1.0rp view
@@ -18,4 +18,4 @@  $TestsOnly$ -concrete Type1 {}+concrete Type1 { }
tests/tests-only/public2.0rp view
@@ -16,4 +16,4 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -concrete Type2 {}+concrete Type2 { }
tests/tests-only2/private.0rx view
@@ -19,5 +19,5 @@ $TestsOnly$  define Testing {-  run () {}+  run () { } }
tests/tests-only3/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../.." path: "tests/tests-only3"-mode: incremental {}+mode: incremental { }
tests/tests-only3/public.0rp view
@@ -16,4 +16,4 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -concrete NotTestsOnly {}+concrete NotTestsOnly { }
tests/tests-only3/public.0rx view
@@ -18,4 +18,4 @@  $TestsOnly$ -define NotTestsOnly {}+define NotTestsOnly { }
tests/tests-only4/.zeolite-module view
@@ -10,4 +10,4 @@     categories: [Type3]   } ]-mode: incremental {}+mode: incremental { }
tests/tests-only4/normal.0rp view
@@ -16,4 +16,4 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -concrete Type3 {}+concrete Type3 { }
tests/tests-only4/testing.0rp view
@@ -18,6 +18,6 @@  $TestsOnly$ -concrete Type1 {}+concrete Type1 { } -@value interface Type2 {}+@value interface Type2 { }
tests/traces/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../.." path: "tests/traces"-mode: incremental {}+mode: incremental { }
tests/traces/traces.0rx view
@@ -16,7 +16,7 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -concrete Test {}+concrete Test { }  define Test {   @type doNotExecute () -> ()
tests/tracing.0rt view
@@ -17,7 +17,7 @@ // Author: Kevin P. Barry [ta0kira@gmail.com]  testcase "NoTrace skips tracing" {-  crash+  failure   require "message"   require "Test\.error"   exclude "Test\.noTrace"@@ -43,7 +43,7 @@ }  testcase "NoTrace works in cleanup" {-  crash+  failure   require "message"   require "Test\.error"   exclude "Test\.noTrace"@@ -66,13 +66,13 @@   error () {     cleanup {       fail("message")-    } in {}+    } in { }   } }   testcase "TraceCreation captures trace" {-  crash+  failure   require "message"   require "Type.+creation" }@@ -103,7 +103,7 @@   require compiler "tracing ignored" } -concrete Test {}+concrete Test { }  define Test {   @type run () -> ()@@ -112,7 +112,7 @@   testcase "TraceCreation still works with NoTrace" {-  crash+  failure   require "message"   require "Type.+creation"   exclude "Type\.call"@@ -140,7 +140,7 @@   testcase "TraceCreation only uses the latest" {-  crash+  failure   require "message"   require "Type1.+creation"   exclude "Type2.+creation"@@ -185,7 +185,7 @@   testcase "correct function name used for non-merged function" {-  crash+  failure   require "message"   require "Type\.call"   exclude "Base"
tests/traverse.0rt view
@@ -25,7 +25,7 @@   traverse (Counter.zeroIndexed(5) -> Int i) {     total <- total+i   }-  \ Testing.checkEquals(total,10)+  \ Testing.checkEquals(total, 10) }  unittest ignoreValue {@@ -33,7 +33,7 @@   traverse (Counter.zeroIndexed(5) -> _) {     total <- total+1   }-  \ Testing.checkEquals(total,5)+  \ Testing.checkEquals(total, 5) }  unittest existingVariable {@@ -42,8 +42,8 @@   traverse (Counter.zeroIndexed(5) -> i) {     total <- total+i   }-  \ Testing.checkEquals(total,10)-  \ Testing.checkEquals(i,4)+  \ Testing.checkEquals(total, 10)+  \ Testing.checkEquals(i, 4) }  unittest breakAtLimit {@@ -54,7 +54,7 @@     }     total <- total+i   }-  \ Testing.checkEquals(total,10)+  \ Testing.checkEquals(total, 10) }  unittest continueOnOdd {@@ -65,7 +65,7 @@     }     total <- total+i   }-  \ Testing.checkEquals(total,20)+  \ Testing.checkEquals(total, 20) }  unittest withUpdate {@@ -77,7 +77,7 @@   } update {     total <- total+i   }-  \ Testing.checkEquals(total,45)+  \ Testing.checkEquals(total, 45) }  unittest overwriteVisibleValue {@@ -86,7 +86,7 @@     // i shouldn't be overwritten after the last iteration.     i <- 0   }-  \ Testing.checkEquals(i,0)+  \ Testing.checkEquals(i, 0) }  unittest overwriteLocalValue {@@ -95,7 +95,7 @@     i <- 0   } update {     // i should also be visible here.-    \ Testing.checkEquals(i,0)+    \ Testing.checkEquals(i, 0)   } } @@ -138,7 +138,7 @@ }  unittest test {-  traverse (0 -> _) {}+  traverse (0 -> _) { } }  @@ -168,7 +168,7 @@ }  unittest test {-  traverse (Empty:new<String>() -> Int i) {}+  traverse (Empty:new<String>() -> Int i) { } }  @@ -191,7 +191,7 @@     traverse (Counter.new() -> Int i) {       total <- total+i     }-    \ Testing.checkEquals(total,10)+    \ Testing.checkEquals(total, 10)   } } @@ -242,7 +242,7 @@     traverse (Counter.new() -> Int i) {       total <- total+i     }-    \ Testing.checkEquals(total,10)+    \ Testing.checkEquals(total, 10)   } } @@ -280,7 +280,7 @@ }  unittest test {-  \ Testing.checkEquals(Test.run("message"),"message")+  \ Testing.checkEquals(Test.run("message"), "message") }  concrete Test {@@ -291,24 +291,24 @@   run (x) (i) {     i <- x     Int total <- 0-    traverse (Repeat:times(x,10) -> i) {+    traverse (Repeat:times(x, 10) -> i) {       total <- total+1     }-    \ Testing.checkEquals(total,10)+    \ Testing.checkEquals(total, 10)   } }  concrete Repeat<|#x> {   refines Order<#x> -  @category times<#y> (#y,Int) -> (optional Repeat<#y>)+  @category times<#y> (#y, Int) -> (optional Repeat<#y>) }  define Repeat {   @value #x value   @value Int count -  times (value,count) {+  times (value, count) {     if (count < 1) {       return empty     } else {
tests/typename.0rt view
@@ -21,94 +21,94 @@ }  unittest string {-  \ Testing.checkEquals(typename<String>().formatted(),"String")+  \ Testing.checkEquals(typename<String>().formatted(), "String") }  unittest int {-  \ Testing.checkEquals(typename<Int>().formatted(),"Int")+  \ Testing.checkEquals(typename<Int>().formatted(), "Int") }  unittest char {-  \ Testing.checkEquals(typename<Char>().formatted(),"Char")+  \ Testing.checkEquals(typename<Char>().formatted(), "Char") }  unittest charBuffer {-  \ Testing.checkEquals(typename<CharBuffer>().formatted(),"CharBuffer")+  \ Testing.checkEquals(typename<CharBuffer>().formatted(), "CharBuffer") }  unittest float {-  \ Testing.checkEquals(typename<Float>().formatted(),"Float")+  \ Testing.checkEquals(typename<Float>().formatted(), "Float") }  unittest bool {-  \ Testing.checkEquals(typename<Bool>().formatted(),"Bool")+  \ Testing.checkEquals(typename<Bool>().formatted(), "Bool") }  unittest anyType {-  \ Testing.checkEquals(typename<any>().formatted(),"any")+  \ Testing.checkEquals(typename<any>().formatted(), "any") }  unittest allType {-  \ Testing.checkEquals(typename<all>().formatted(),"all")+  \ Testing.checkEquals(typename<all>().formatted(), "all") }  unittest intersectDedup {-  \ Testing.checkEquals(typename<[AsBool&Char&Formatted&Int]>().formatted(),-                           typename<[Char&Int]>().formatted())+  \ Testing.checkEquals(typename<[AsBool & Char & Formatted & Int]>().formatted(),+                           typename<[Char & Int]>().formatted()) }  unittest unionDedup {-  \ Testing.checkEquals(typename<[AsBool|Char|Formatted|Int]>().formatted(),-                           typename<[AsBool|Formatted]>().formatted())+  \ Testing.checkEquals(typename<[AsBool | Char | Formatted | Int]>().formatted(),+                           typename<[AsBool | Formatted]>().formatted()) }  unittest param {-  \ Testing.checkEquals(Wrapped:getTypename<String,Value<Int>>().formatted(),+  \ Testing.checkEquals(Wrapped:getTypename<String, Value<Int>>().formatted(),                            "Type<String,Value<Int>>") }  unittest intersectParam {-  String text <- Wrapped:getTypenameIntersect<Formatted,Int>().formatted()+  String text <- Wrapped:getTypenameIntersect<Formatted, Int>().formatted()   if (text != "[Formatted&Int]") {     fail(text)   } }  unittest unionParam {-  String text <- Wrapped:getTypenameUnion<Formatted,Int>().formatted()+  String text <- Wrapped:getTypenameUnion<Formatted, Int>().formatted()   if (text != "[Formatted|Int]") {     fail(text)   } }  unittest intersectDedupParam {-  \ Testing.checkEquals(Wrapped:getTypenameIntersect<Int,Int>().formatted(),"Int")+  \ Testing.checkEquals(Wrapped:getTypenameIntersect<Int, Int>().formatted(), "Int") }  unittest unionDedupParam {-  \ Testing.checkEquals(Wrapped:getTypenameUnion<Int,Int>().formatted(),"Int")+  \ Testing.checkEquals(Wrapped:getTypenameUnion<Int, Int>().formatted(), "Int") } -@value interface Value<#x> {}+@value interface Value<#x> { } -@value interface Type<#x,#y> {}+@value interface Type<#x, #y> { }  concrete Wrapped {-  @category getTypename<#x,#y> () -> (Formatted)-  @category getTypenameIntersect<#x,#y> () -> (Formatted)-  @category getTypenameUnion<#x,#y> () -> (Formatted)+  @category getTypename<#x, #y> () -> (Formatted)+  @category getTypenameIntersect<#x, #y> () -> (Formatted)+  @category getTypenameUnion<#x, #y> () -> (Formatted) }  define Wrapped {   getTypename () {-    return typename<Type<#x,#y>>()+    return typename<Type<#x, #y>>()   }    getTypenameIntersect () {-    return typename<[#x&#y]>()+    return typename<[#x & #y]>()   }    getTypenameUnion () {-    return typename<[#x|#y]>()+    return typename<[#x | #y]>()   } }
tests/unary-functions.0rt view
@@ -126,12 +126,12 @@ }  concrete Test {-  @category add (Int,Int) -> (Int)+  @category add (Int, Int) -> (Int)   @category neg (Int) -> (Int) }  define Test {-  add (x,y) {+  add (x, y) {     return x + y   } @@ -147,7 +147,7 @@  unittest requireUnary {   optional Int value <- 1-  \ Testing.checkEquals(`require` value,1)+  \ Testing.checkEquals(`require` value, 1) }  unittest presentUnary {@@ -165,6 +165,6 @@ }  unittest reduceUnary {-  optional Formatted value <- `reduce<Int,Formatted>` 123-  \ Testing.checkEquals(require(value).formatted(),"123")+  optional Formatted value <- `reduce<Int, Formatted>` 123+  \ Testing.checkEquals(require(value).formatted(), "123") }
tests/unreachable.0rt view
@@ -43,7 +43,7 @@   require compiler "unreachable" } -concrete Test {}+concrete Test { }  define Test {   @category failedReturn () -> (Int)@@ -59,7 +59,7 @@   require compiler "unreachable" } -concrete Test {}+concrete Test { }  define Test {   @category failedReturn () -> (Int)@@ -79,7 +79,7 @@   require compiler "unreachable" } -concrete Test {}+concrete Test { }  define Test {   @category failedReturn () -> (Int)@@ -128,7 +128,7 @@     fail("message")   } cleanup {     \ empty-  } in {}+  } in { } }  
tests/visibility/.zeolite-module view
@@ -3,4 +3,4 @@ private_deps: [   "internal" ]-mode: incremental {}+mode: incremental { }
tests/visibility/internal/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../.." path: "visibility/internal"-mode: incremental {}+mode: incremental { }
tests/visibility2/.zeolite-module view
@@ -3,4 +3,4 @@ private_deps: [   "internal" ]-mode: incremental {}+mode: incremental { }
tests/visibility2/internal/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../.." path: "visibility2/internal"-mode: incremental {}+mode: incremental { }
tests/warn-public/.zeolite-module view
@@ -4,4 +4,4 @@   "internal"   "internal2" ]-mode: incremental {}+mode: incremental { }
tests/warn-public/internal/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../../.." path: "tests/warn-public/internal"-mode: incremental {}+mode: incremental { }
tests/warn-public/internal/public.0rp view
@@ -16,4 +16,4 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -@value interface Type1 {}+@value interface Type1 { }
tests/warn-public/internal2/.zeolite-module view
@@ -1,3 +1,3 @@ root: "../../.." path: "tests/warn-public/internal2"-mode: incremental {}+mode: incremental { }
tests/warn-public/internal2/public.0rp view
@@ -16,4 +16,4 @@  // Author: Kevin P. Barry [ta0kira@gmail.com] -@value interface Type2 {}+@value interface Type2 { }
tests/while.0rt view
@@ -21,9 +21,9 @@   require "value.+initialized" } -@value interface Value {}+@value interface Value { } -concrete Test {}+concrete Test { }  define Test {   @value process () -> (optional Value)@@ -40,9 +40,9 @@   require "return" } -@value interface Value {}+@value interface Value { } -concrete Test {}+concrete Test { }  define Test {   @value process () -> (optional Value)@@ -295,7 +295,7 @@   testcase "crash in while" {-  crash+  failure   require "empty" } @@ -336,7 +336,7 @@     while (true) {       cleanup {         fail(message)-      } in {}+      } in { }     }     return "return"   }@@ -353,7 +353,7 @@   while(true) {     cleanup {       break-    } in {}+    } in { }   } } @@ -368,7 +368,7 @@   while(true) {     cleanup {       continue-    } in {}+    } in { }   } } @@ -432,7 +432,7 @@   testcase "return set in predicate" {-  crash+  failure   require "message" } 
zeolite-lang.cabal view
@@ -1,7 +1,7 @@ cabal-version:       2.2  name:                zeolite-lang-version:             0.23.0.0+version:             0.24.0.0 synopsis:            Zeolite is a statically-typed, general-purpose programming language.  description:@@ -59,7 +59,7 @@ license-file:        LICENSE author:              Kevin P. Barry maintainer:          Kevin P. Barry <ta0kira@gmail.com>-copyright:           (c) Kevin P. Barry 2019-2022+copyright:           (c) Kevin P. Barry 2019-2023 category:            Compiler build-type:          Simple @@ -102,8 +102,8 @@                      lib/container/*.0rp,                      lib/container/src/*.0rp,                      lib/container/src/*.0rx,-                     lib/container/test/*.0rt,                      lib/container/src/*.cpp,+                     lib/container/test/*.0rt,                      lib/file/README.md,                      lib/file/.zeolite-module,                      lib/file/*.0rp,@@ -120,7 +120,11 @@                      lib/testing/README.md,                      lib/testing/.zeolite-module,                      lib/testing/*.0rp,+                     lib/testing/src/*.0rp,                      lib/testing/src/*.0rx,+                     lib/testing/src/*.cpp,+                     lib/testing/test/*.0rp,+                     lib/testing/test/*.0rx,                      lib/testing/test/*.0rt,                      lib/thread/README.md,                      lib/thread/.zeolite-module,@@ -147,6 +151,9 @@                      tests/check-defs/.zeolite-module,                      tests/check-defs/*.0rp,                      tests/check-defs/*.0rx,+                     tests/custom-testcase/README.md,+                     tests/custom-testcase/.zeolite-module,+                     tests/custom-testcase/*.0rt,                      tests/fast-static/README.md,                      tests/fast-static/*.0rx,                      tests/freshness/.zeolite-module,@@ -320,20 +327,20 @@                        TypeSynonymInstances,                        Unsafe -  build-depends:       base >= 4.9 && < 4.15,+  build-depends:       base >= 4.9 && < 4.20,                        containers >= 0.3 && < 0.7,                        directory >= 1.2.3 && < 1.4,                        filepath >= 1.0 && < 1.5,-                       hashable >= 1.0 && < 1.4,-                       megaparsec >= 7.0 && < 9.1,+                       hashable >= 1.0 && < 1.5,+                       megaparsec >= 7.0 && < 9.7,                        microlens >= 0.4.9 && < 0.5,                        microlens-th >= 0.1.0.0 && < 0.5,-                       mtl >= 1.0 && < 2.3,+                       mtl >= 1.0 && < 2.4,                        parser-combinators >= 0.2 && < 2.0,                        regex-tdfa >= 1.0 && < 1.4,-                       time >= 1.0 && < 1.11,-                       transformers >= 0.1 && < 0.6,-                       unix >= 2.6 && <= 2.8+                       time >= 1.0 && < 1.13,+                       transformers >= 0.1 && < 0.7,+                       unix >= 2.6 && <= 2.9    hs-source-dirs:      src