packages feed

zeolite-lang 0.3.0.0 → 0.4.0.0

raw patch · 44 files changed

+2276/−2102 lines, 44 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Cli.CompileMetadata: [cmExtraRequires] :: CompileMetadata -> [CategoryIdentifier]
- Cli.CompileMetadata: [rmExternalDefs] :: ModuleConfig -> [String]
- Cli.CompileMetadata: [rmExtraRequires] :: ModuleConfig -> [String]
- Cli.CompileMetadata: [rmOutputName] :: ModuleConfig -> String
- Cli.CompileOptions: [coExternalDefs] :: CompileOptions -> [String]
- Cli.CompileOptions: [coExtraRequires] :: CompileOptions -> [String]
- Cli.CompileOptions: [coOutputName] :: CompileOptions -> String
- Cli.ProcessMetadata: getRequiresFromDeps :: [CompileMetadata] -> [CategoryIdentifier]
+ Cli.CompileMetadata: [cmLinkFlags] :: CompileMetadata -> [String]
+ Cli.CompileOptions: CategorySource :: String -> [String] -> [String] -> ExtraSource
+ Cli.CompileOptions: OtherSource :: String -> ExtraSource
+ Cli.CompileOptions: [cbLinkFlags] :: CompileMode -> [String]
+ Cli.CompileOptions: [cbOutputName] :: CompileMode -> String
+ Cli.CompileOptions: [ciLinkFlags] :: CompileMode -> [String]
+ Cli.CompileOptions: [csCategories] :: ExtraSource -> [String]
+ Cli.CompileOptions: [csDepCategories] :: ExtraSource -> [String]
+ Cli.CompileOptions: [csSource] :: ExtraSource -> String
+ Cli.CompileOptions: [osSource] :: ExtraSource -> String
+ Cli.CompileOptions: data ExtraSource
+ Cli.CompileOptions: getLinkFlags :: CompileMode -> [String]
+ Cli.CompileOptions: getSourceCategories :: ExtraSource -> [String]
+ Cli.CompileOptions: getSourceDeps :: ExtraSource -> [String]
+ Cli.CompileOptions: getSourceFile :: ExtraSource -> String
+ Cli.CompileOptions: instance GHC.Classes.Eq Cli.CompileOptions.ExtraSource
+ Cli.CompileOptions: instance GHC.Show.Show Cli.CompileOptions.ExtraSource
+ Cli.ParseMetadata: instance Cli.ParseMetadata.ConfigFormat Cli.CompileOptions.ExtraSource
+ Cli.ProcessMetadata: getLinkFlagsForDeps :: [CompileMetadata] -> [String]
+ CompilerCxx.Procedure: categoriesFromTypes :: GeneralInstance -> Set CategoryName
+ Config.Programs: [ctbLinkFlags] :: CxxCommand -> [String]
+ Config.Programs: [ctbPaths] :: CxxCommand -> [String]
- Cli.CompileMetadata: CompileMetadata :: String -> String -> String -> [String] -> [String] -> [CategoryIdentifier] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [ObjectFile] -> CompileMetadata
+ Cli.CompileMetadata: CompileMetadata :: String -> String -> String -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> [ObjectFile] -> CompileMetadata
- Cli.CompileMetadata: ModuleConfig :: String -> String -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> CompileMode -> String -> ModuleConfig
+ Cli.CompileMetadata: ModuleConfig :: String -> String -> [String] -> [String] -> [ExtraSource] -> [String] -> CompileMode -> ModuleConfig
- Cli.CompileMetadata: [rmExtraFiles] :: ModuleConfig -> [String]
+ Cli.CompileMetadata: [rmExtraFiles] :: ModuleConfig -> [ExtraSource]
- Cli.CompileOptions: CompileBinary :: String -> String -> CompileMode
+ Cli.CompileOptions: CompileBinary :: String -> String -> String -> [String] -> CompileMode
- Cli.CompileOptions: CompileIncremental :: CompileMode
+ Cli.CompileOptions: CompileIncremental :: [String] -> CompileMode
- Cli.CompileOptions: CompileOptions :: HelpMode -> [String] -> [String] -> [String] -> [String] -> [String] -> [String] -> String -> [String] -> CompileMode -> String -> ForceMode -> CompileOptions
+ Cli.CompileOptions: CompileOptions :: HelpMode -> [String] -> [String] -> [String] -> [ExtraSource] -> [String] -> String -> CompileMode -> ForceMode -> CompileOptions
- Cli.CompileOptions: [coExtraFiles] :: CompileOptions -> [String]
+ Cli.CompileOptions: [coExtraFiles] :: CompileOptions -> [ExtraSource]
- Cli.ProcessMetadata: getObjectFileResolver :: [CategoryIdentifier] -> [ObjectFile] -> [Namespace] -> [CategoryName] -> [String]
+ Cli.ProcessMetadata: getObjectFileResolver :: [ObjectFile] -> [Namespace] -> [CategoryName] -> [String]
- Config.Programs: CompileToBinary :: String -> [String] -> String -> [String] -> CxxCommand
+ Config.Programs: CompileToBinary :: String -> [String] -> String -> [String] -> [String] -> CxxCommand

Files

ChangeLog.md view
@@ -1,5 +1,22 @@ # Revision history for zeolite-lang +## 0.4.0.0  -- 2020-05-05++* **[new]** Allows modules to specify custom linker flags and private include+  paths in `.zeolite-module`. This lets categories written in C++ depend on+  external libraries written in other languages.++* **[behavior]** Adds optimization of dependency inclusion for categories that+  are defined in C++ sources. This should eliminate linking in object files that+  are not needed by the binary.++* **[behavior]** Adds checks to prevent a module from defining a category that+  was declared in another module.++* **[breaking]** Updates the `.zeolite-module` format to require associating+  externally-defined categories with the source files that define them. This+  allows finer-grained linking of binaries and tests.+ ## 0.3.0.0  -- 2020-05-03  * **[breaking]** Updates syntax for discarding all returns to use `\` instead of
base/.zeolite-module view
@@ -1,9 +1,27 @@ root: ".." path: "base" extra_files: [+  category_source {+    source: "base/Category_Bool.cpp"+    categories: [Bool]+  }+  category_source {+    source: "base/Category_Char.cpp"+    categories: [Char]+  }+  category_source {+    source: "base/Category_Float.cpp"+    categories: [Float]+  }+  category_source {+    source: "base/Category_Int.cpp"+    categories: [Int]+  }+  category_source {+    source: "base/Category_String.cpp"+    categories: [String]+  }   "base/argv.cpp"-  "base/builtin.cpp"-  "base/builtin.hpp"   "base/category-header.hpp"   "base/category-source.cpp"   "base/category-source.hpp"@@ -13,35 +31,8 @@   "base/logging.hpp"   "base/types.cpp"   "base/types.hpp"-  "capture-thread/include/thread-capture.h"-  "capture-thread/include/thread-crosser.h"-  "capture-thread/src/thread-crosser.cc"-]-extra_paths: [-  "base"-  "capture-thread/include"-]-always_include: [-  AsBool-  AsChar-  AsFloat-  AsInt-  AsString-  Bool-  Char-  Equals-  Float-  Formatted-  Int-  LessThan-  ReadPosition-  String-]-external: [-  Bool-  Char-  Float-  Int-  String+  "base/thread-capture.h"+  "base/thread-crosser.h"+  "base/thread-crosser.cc" ]-mode: incremental+mode: incremental {}
+ base/Category_Bool.cpp view
@@ -0,0 +1,214 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2020 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++#include "Category_Bool.hpp"++#include <map>+#include <sstream>++#include "category-source.hpp"+#include "Category_AsBool.hpp"+#include "Category_AsInt.hpp"+#include "Category_AsFloat.hpp"+#include "Category_Formatted.hpp"+#include "Category_Equals.hpp"+++#ifdef ZEOLITE_DYNAMIC_NAMESPACE+namespace ZEOLITE_DYNAMIC_NAMESPACE {+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+namespace {+const int collection_Bool = 0;+}  // namespace+const void* const Functions_Bool = &collection_Bool;+namespace {+class Category_Bool;+class Type_Bool;+Type_Bool& CreateType_Bool(Params<0>::Type params);+class Value_Bool;+S<TypeValue> CreateValue(Type_Bool& parent, const ParamTuple& params, const ValueTuple& args);+struct Category_Bool : public TypeCategory {+  std::string CategoryName() const final { return "Bool"; }+  Category_Bool() {+    CycleCheck<Category_Bool>::Check();+    CycleCheck<Category_Bool> marker(*this);+    TRACE_FUNCTION("Bool (init @category)")+  }+  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Category_Bool::*)(const ParamTuple&, const ValueTuple&);+    return TypeCategory::Dispatch(label, params, args);+  }+};+Category_Bool& CreateCategory_Bool() {+  static auto& category = *new Category_Bool();+  return category;+}+struct Type_Bool : public TypeInstance {+  std::string CategoryName() const final { return parent.CategoryName(); }+  void BuildTypeName(std::ostream& output) const final {+    return TypeInstance::TypeNameFrom(output, parent);+  }+  Category_Bool& parent;+  bool CanConvertFrom(const TypeInstance& from) const final {+    std::vector<const TypeInstance*> args;+    if (!from.TypeArgsForParent(parent, args)) return false;+    if(args.size() != 0) {+      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();+    }+    return true;+  }+  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {+    if (&category == &GetCategory_Bool()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsBool()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsInt()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsFloat()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_Formatted()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    return false;+  }+  Type_Bool(Category_Bool& p, Params<0>::Type params) : parent(p) {+    CycleCheck<Type_Bool>::Check();+    CycleCheck<Type_Bool> marker(*this);+    TRACE_FUNCTION("Bool (init @type)")+  }+  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Type_Bool::*)(const ParamTuple&, const ValueTuple&);+    static const CallType Table_Equals[] = {+      &Type_Bool::Call_equals,+    };+    if (label.collection == Functions_Equals) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Equals[label.function_num])(params, args);+    }+    return TypeInstance::Dispatch(label, params, args);+  }+  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);+};+Type_Bool& CreateType_Bool(Params<0>::Type params) {+  static auto& cache = *new InstanceMap<0,Type_Bool>();+  auto& cached = cache[params];+  if (!cached) { cached = R_get(new Type_Bool(CreateCategory_Bool(), params)); }+  return *cached;+}+struct Value_Bool : public TypeValue {+  Value_Bool(Type_Bool& p, bool value) : parent(p), value_(value) {}+  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {+    using CallType = ReturnTuple(Value_Bool::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);+    static const CallType Table_AsBool[] = {+      &Value_Bool::Call_asBool,+    };+    static const CallType Table_AsFloat[] = {+      &Value_Bool::Call_asFloat,+    };+    static const CallType Table_AsInt[] = {+      &Value_Bool::Call_asInt,+    };+    static const CallType Table_Formatted[] = {+      &Value_Bool::Call_formatted,+    };+    if (label.collection == Functions_AsBool) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsBool[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsFloat) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsFloat[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsInt) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsInt[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_Formatted) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Formatted[label.function_num])(self, params, args);+    }+    return TypeValue::Dispatch(self, label, params, args);+  }+  std::string CategoryName() const final { return parent.CategoryName(); }+  bool AsBool() const final { return value_; }+  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  Type_Bool& parent;+  const bool value_;+};+ReturnTuple Type_Bool::Call_equals(const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Bool.equals")+  const bool Var_arg1 = (args.At(0))->AsBool();+  const bool Var_arg2 = (args.At(1))->AsBool();+  return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));+}+ReturnTuple Value_Bool::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Bool.asBool")+  return ReturnTuple(Var_self);+}+ReturnTuple Value_Bool::Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Bool.asFloat")+  return ReturnTuple(Box_Float(value_ ? 1.0 : 0.0));+}+ReturnTuple Value_Bool::Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Bool.asInt")+  return ReturnTuple(Box_Int(value_? 1 : 0));+}+ReturnTuple Value_Bool::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Bool.formatted")+  return ReturnTuple(Box_String(value_? "true" : "false"));+}+const S<TypeValue>& Var_true = *new S<TypeValue>(new Value_Bool(CreateType_Bool(Params<0>::Type()), true));+const S<TypeValue>& Var_false = *new S<TypeValue>(new Value_Bool(CreateType_Bool(Params<0>::Type()), false));+}  // namespace+TypeCategory& GetCategory_Bool() {+  return CreateCategory_Bool();+}+TypeInstance& GetType_Bool(Params<0>::Type params) {+  return CreateType_Bool(params);+}+#ifdef ZEOLITE_DYNAMIC_NAMESPACE+}  // namespace ZEOLITE_DYNAMIC_NAMESPACE+using namespace ZEOLITE_DYNAMIC_NAMESPACE;+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+++S<TypeValue> Box_Bool(bool value) {+  return value? Var_true : Var_false;+}
+ base/Category_Char.cpp view
@@ -0,0 +1,250 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2020 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++#include "Category_Char.hpp"++#include <map>+#include <sstream>++#include "category-source.hpp"+#include "Category_AsBool.hpp"+#include "Category_AsChar.hpp"+#include "Category_AsInt.hpp"+#include "Category_AsFloat.hpp"+#include "Category_Formatted.hpp"+#include "Category_Equals.hpp"+#include "Category_LessThan.hpp"+++#ifdef ZEOLITE_DYNAMIC_NAMESPACE+namespace ZEOLITE_DYNAMIC_NAMESPACE {+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+namespace {+const int collection_Char = 0;+}  // namespace+const void* const Functions_Char = &collection_Char;+namespace {+class Category_Char;+class Type_Char;+Type_Char& CreateType_Char(Params<0>::Type params);+class Value_Char;+S<TypeValue> CreateValue(Type_Char& parent, const ParamTuple& params, const ValueTuple& args);+struct Category_Char : public TypeCategory {+  std::string CategoryName() const final { return "Char"; }+  Category_Char() {+    CycleCheck<Category_Char>::Check();+    CycleCheck<Category_Char> marker(*this);+    TRACE_FUNCTION("Char (init @category)")+  }+  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Category_Char::*)(const ParamTuple&, const ValueTuple&);+    return TypeCategory::Dispatch(label, params, args);+  }+};+Category_Char& CreateCategory_Char() {+  static auto& category = *new Category_Char();+  return category;+}+struct Type_Char : public TypeInstance {+  std::string CategoryName() const final { return parent.CategoryName(); }+  void BuildTypeName(std::ostream& output) const final {+    return TypeInstance::TypeNameFrom(output, parent);+  }+  Category_Char& parent;+  bool CanConvertFrom(const TypeInstance& from) const final {+    std::vector<const TypeInstance*> args;+    if (!from.TypeArgsForParent(parent, args)) return false;+    if(args.size() != 0) {+      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();+    }+    return true;+  }+  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {+    if (&category == &GetCategory_Char()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsBool()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsChar()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsInt()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsFloat()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_Formatted()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    return false;+  }+  Type_Char(Category_Char& p, Params<0>::Type params) : parent(p) {+    CycleCheck<Type_Char>::Check();+    CycleCheck<Type_Char> marker(*this);+    TRACE_FUNCTION("Char (init @type)")+  }+  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Type_Char::*)(const ParamTuple&, const ValueTuple&);+    static const CallType Table_Equals[] = {+      &Type_Char::Call_equals,+    };+    static const CallType Table_LessThan[] = {+      &Type_Char::Call_lessThan,+    };+    if (label.collection == Functions_Equals) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Equals[label.function_num])(params, args);+    }+    if (label.collection == Functions_LessThan) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_LessThan[label.function_num])(params, args);+    }+    return TypeInstance::Dispatch(label, params, args);+  }+  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_lessThan(const ParamTuple& params, const ValueTuple& args);+};+Type_Char& CreateType_Char(Params<0>::Type params) {+  static auto& cache = *new InstanceMap<0,Type_Char>();+  auto& cached = cache[params];+  if (!cached) { cached = R_get(new Type_Char(CreateCategory_Char(), params)); }+  return *cached;+}+struct Value_Char : public TypeValue {+  Value_Char(Type_Char& p, PrimChar value) : parent(p), value_(value) {}+  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {+    using CallType = ReturnTuple(Value_Char::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);+    static const CallType Table_AsBool[] = {+      &Value_Char::Call_asBool,+    };+    static const CallType Table_AsChar[] = {+      &Value_Char::Call_asChar,+    };+    static const CallType Table_AsFloat[] = {+      &Value_Char::Call_asFloat,+    };+    static const CallType Table_AsInt[] = {+      &Value_Char::Call_asInt,+    };+    static const CallType Table_Formatted[] = {+      &Value_Char::Call_formatted,+    };+    if (label.collection == Functions_AsBool) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsBool[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsChar) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsChar[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsFloat) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsFloat[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsInt) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsInt[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_Formatted) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Formatted[label.function_num])(self, params, args);+    }+    return TypeValue::Dispatch(self, label, params, args);+  }+  std::string CategoryName() const final { return parent.CategoryName(); }+  PrimChar AsChar() const final { return value_; }+  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asChar(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  Type_Char& parent;+  const PrimChar value_;+};+ReturnTuple Type_Char::Call_equals(const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Char.equals")+  const PrimChar Var_arg1 = (args.At(0))->AsChar();+  const PrimChar Var_arg2 = (args.At(1))->AsChar();+      return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));+}+ReturnTuple Type_Char::Call_lessThan(const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Char.lessThan")+  const PrimChar Var_arg1 = (args.At(0))->AsChar();+  const PrimChar Var_arg2 = (args.At(1))->AsChar();+  return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));+}+ReturnTuple Value_Char::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Char.asBool")+  return ReturnTuple(Box_Bool(value_ != '\0'));+}+ReturnTuple Value_Char::Call_asChar(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Char.asChar")+  return ReturnTuple(Var_self);+}+ReturnTuple Value_Char::Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Char.asFloat")+  return ReturnTuple(Box_Float(value_));+}+ReturnTuple Value_Char::Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Char.asInt")+  return ReturnTuple(Box_Int(value_));+}+ReturnTuple Value_Char::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Char.formatted")+  std::ostringstream output;+  output << value_;+  return ReturnTuple(Box_String(output.str()));+}+}  // namespace+TypeCategory& GetCategory_Char() {+  return CreateCategory_Char();+}+TypeInstance& GetType_Char(Params<0>::Type params) {+  return CreateType_Char(params);+}+#ifdef ZEOLITE_DYNAMIC_NAMESPACE+}  // namespace ZEOLITE_DYNAMIC_NAMESPACE+using namespace ZEOLITE_DYNAMIC_NAMESPACE;+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+++S<TypeValue> Box_Char(PrimChar value) {+  return S_get(new Value_Char(CreateType_Char(Params<0>::Type()), value));+}
+ base/Category_Float.cpp view
@@ -0,0 +1,231 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2020 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++#include "Category_Float.hpp"++#include <map>+#include <sstream>++#include "category-source.hpp"+#include "Category_AsBool.hpp"+#include "Category_AsInt.hpp"+#include "Category_AsFloat.hpp"+#include "Category_Formatted.hpp"+#include "Category_Equals.hpp"+#include "Category_LessThan.hpp"+++#ifdef ZEOLITE_DYNAMIC_NAMESPACE+namespace ZEOLITE_DYNAMIC_NAMESPACE {+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+namespace {+const int collection_Float = 0;+}  // namespace+const void* const Functions_Float = &collection_Float;+namespace {+class Category_Float;+class Type_Float;+Type_Float& CreateType_Float(Params<0>::Type params);+class Value_Float;+S<TypeValue> CreateValue(Type_Float& parent, const ParamTuple& params, const ValueTuple& args);+struct Category_Float : public TypeCategory {+  std::string CategoryName() const final { return "Float"; }+  Category_Float() {+    CycleCheck<Category_Float>::Check();+    CycleCheck<Category_Float> marker(*this);+    TRACE_FUNCTION("Float (init @category)")+  }+  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Category_Float::*)(const ParamTuple&, const ValueTuple&);+    return TypeCategory::Dispatch(label, params, args);+  }+};+Category_Float& CreateCategory_Float() {+  static auto& category = *new Category_Float();+  return category;+}+struct Type_Float : public TypeInstance {+  std::string CategoryName() const final { return parent.CategoryName(); }+  void BuildTypeName(std::ostream& output) const final {+    return TypeInstance::TypeNameFrom(output, parent);+  }+  Category_Float& parent;+  bool CanConvertFrom(const TypeInstance& from) const final {+    std::vector<const TypeInstance*> args;+    if (!from.TypeArgsForParent(parent, args)) return false;+    if(args.size() != 0) {+      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();+    }+    return true;+  }+  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {+    if (&category == &GetCategory_Float()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsBool()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsInt()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsFloat()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_Formatted()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    return false;+  }+  Type_Float(Category_Float& p, Params<0>::Type params) : parent(p) {+    CycleCheck<Type_Float>::Check();+    CycleCheck<Type_Float> marker(*this);+    TRACE_FUNCTION("Float (init @type)")+  }+  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Type_Float::*)(const ParamTuple&, const ValueTuple&);+    static const CallType Table_Equals[] = {+      &Type_Float::Call_equals,+    };+    static const CallType Table_LessThan[] = {+      &Type_Float::Call_lessThan,+    };+    if (label.collection == Functions_Equals) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Equals[label.function_num])(params, args);+    }+    if (label.collection == Functions_LessThan) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_LessThan[label.function_num])(params, args);+    }+    return TypeInstance::Dispatch(label, params, args);+  }+  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_lessThan(const ParamTuple& params, const ValueTuple& args);+};+Type_Float& CreateType_Float(Params<0>::Type params) {+  static auto& cache = *new InstanceMap<0,Type_Float>();+  auto& cached = cache[params];+  if (!cached) { cached = R_get(new Type_Float(CreateCategory_Float(), params)); }+  return *cached;+}+struct Value_Float : public TypeValue {+  Value_Float(Type_Float& p, PrimFloat value) : parent(p), value_(value) {}+  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {+    using CallType = ReturnTuple(Value_Float::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);+    static const CallType Table_AsBool[] = {+      &Value_Float::Call_asBool,+    };+    static const CallType Table_AsFloat[] = {+      &Value_Float::Call_asFloat,+    };+    static const CallType Table_AsInt[] = {+      &Value_Float::Call_asInt,+    };+    static const CallType Table_Formatted[] = {+      &Value_Float::Call_formatted,+    };+    if (label.collection == Functions_AsBool) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsBool[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsFloat) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsFloat[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsInt) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsInt[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_Formatted) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Formatted[label.function_num])(self, params, args);+    }+    return TypeValue::Dispatch(self, label, params, args);+  }+  std::string CategoryName() const final { return parent.CategoryName(); }+  PrimFloat AsFloat() const final { return value_; }+  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  Type_Float& parent;+  const PrimFloat value_;+};+ReturnTuple Type_Float::Call_equals(const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Float.equals")+  const PrimFloat Var_arg1 = (args.At(0))->AsFloat();+  const PrimFloat Var_arg2 = (args.At(1))->AsFloat();+  return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));+}+ReturnTuple Type_Float::Call_lessThan(const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Float.lessThan")+  const PrimFloat Var_arg1 = (args.At(0))->AsFloat();+  const PrimFloat Var_arg2 = (args.At(1))->AsFloat();+  return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));+}+ReturnTuple Value_Float::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Float.asBool")+  return ReturnTuple(Box_Bool(value_ != 0.0));+}+ReturnTuple Value_Float::Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Float.asFloat")+  return ReturnTuple(Var_self);+}+ReturnTuple Value_Float::Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Float.asInt")+  return ReturnTuple(Box_Int(value_));+}+ReturnTuple Value_Float::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Float.formatted")+  std::ostringstream output;+  output << value_;+  return ReturnTuple(Box_String(output.str()));+}+}  // namespace+TypeCategory& GetCategory_Float() {+  return CreateCategory_Float();+}+TypeInstance& GetType_Float(Params<0>::Type params) {+  return CreateType_Float(params);+}+#ifdef ZEOLITE_DYNAMIC_NAMESPACE+}  // namespace ZEOLITE_DYNAMIC_NAMESPACE+using namespace ZEOLITE_DYNAMIC_NAMESPACE;+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+++S<TypeValue> Box_Float(PrimFloat value) {+  return S_get(new Value_Float(CreateType_Float(Params<0>::Type()), value));+}
+ base/Category_Int.cpp view
@@ -0,0 +1,250 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2020 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++#include "Category_Int.hpp"++#include <map>+#include <sstream>++#include "category-source.hpp"+#include "Category_AsBool.hpp"+#include "Category_AsChar.hpp"+#include "Category_AsInt.hpp"+#include "Category_AsFloat.hpp"+#include "Category_Formatted.hpp"+#include "Category_Equals.hpp"+#include "Category_LessThan.hpp"+++#ifdef ZEOLITE_DYNAMIC_NAMESPACE+namespace ZEOLITE_DYNAMIC_NAMESPACE {+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+namespace {+const int collection_Int = 0;+}  // namespace+const void* const Functions_Int = &collection_Int;+namespace {+class Category_Int;+class Type_Int;+Type_Int& CreateType_Int(Params<0>::Type params);+class Value_Int;+S<TypeValue> CreateValue(Type_Int& parent, const ParamTuple& params, const ValueTuple& args);+struct Category_Int : public TypeCategory {+  std::string CategoryName() const final { return "Int"; }+  Category_Int() {+    CycleCheck<Category_Int>::Check();+    CycleCheck<Category_Int> marker(*this);+    TRACE_FUNCTION("Int (init @category)")+  }+  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Category_Int::*)(const ParamTuple&, const ValueTuple&);+    return TypeCategory::Dispatch(label, params, args);+  }+};+Category_Int& CreateCategory_Int() {+  static auto& category = *new Category_Int();+  return category;+}+struct Type_Int : public TypeInstance {+  std::string CategoryName() const final { return parent.CategoryName(); }+  void BuildTypeName(std::ostream& output) const final {+    return TypeInstance::TypeNameFrom(output, parent);+  }+  Category_Int& parent;+  bool CanConvertFrom(const TypeInstance& from) const final {+    std::vector<const TypeInstance*> args;+    if (!from.TypeArgsForParent(parent, args)) return false;+    if(args.size() != 0) {+      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();+    }+    return true;+  }+  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {+    if (&category == &GetCategory_Int()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsBool()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsChar()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsInt()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsFloat()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_Formatted()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    return false;+  }+  Type_Int(Category_Int& p, Params<0>::Type params) : parent(p) {+    CycleCheck<Type_Int>::Check();+    CycleCheck<Type_Int> marker(*this);+    TRACE_FUNCTION("Int (init @type)")+  }+  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Type_Int::*)(const ParamTuple&, const ValueTuple&);+    static const CallType Table_Equals[] = {+      &Type_Int::Call_equals,+    };+    static const CallType Table_LessThan[] = {+      &Type_Int::Call_lessThan,+    };+    if (label.collection == Functions_Equals) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Equals[label.function_num])(params, args);+    }+    if (label.collection == Functions_LessThan) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_LessThan[label.function_num])(params, args);+    }+    return TypeInstance::Dispatch(label, params, args);+  }+  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_lessThan(const ParamTuple& params, const ValueTuple& args);+};+Type_Int& CreateType_Int(Params<0>::Type params) {+  static auto& cache = *new InstanceMap<0,Type_Int>();+  auto& cached = cache[params];+  if (!cached) { cached = R_get(new Type_Int(CreateCategory_Int(), params)); }+  return *cached;+}+struct Value_Int : public TypeValue {+  Value_Int(Type_Int& p, PrimInt value) : parent(p), value_(value) {}+  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {+    using CallType = ReturnTuple(Value_Int::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);+    static const CallType Table_AsBool[] = {+      &Value_Int::Call_asBool,+    };+    static const CallType Table_AsChar[] = {+      &Value_Int::Call_asChar,+    };+    static const CallType Table_AsFloat[] = {+      &Value_Int::Call_asFloat,+    };+    static const CallType Table_AsInt[] = {+      &Value_Int::Call_asInt,+    };+    static const CallType Table_Formatted[] = {+      &Value_Int::Call_formatted,+    };+    if (label.collection == Functions_AsBool) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsBool[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsChar) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsChar[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsFloat) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsFloat[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_AsInt) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsInt[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_Formatted) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Formatted[label.function_num])(self, params, args);+    }+    return TypeValue::Dispatch(self, label, params, args);+  }+  std::string CategoryName() const final { return parent.CategoryName(); }+  PrimInt AsInt() const final { return value_; }+  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asChar(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  Type_Int& parent;+  const PrimInt value_;+};+ReturnTuple Type_Int::Call_equals(const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Int.equals")+  const PrimInt Var_arg1 = (args.At(0))->AsInt();+  const PrimInt Var_arg2 = (args.At(1))->AsInt();+  return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));+}+ReturnTuple Type_Int::Call_lessThan(const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Int.lessThan")+  const PrimInt Var_arg1 = (args.At(0))->AsInt();+  const PrimInt Var_arg2 = (args.At(1))->AsInt();+  return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));+}+ReturnTuple Value_Int::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Int.asBool")+  return ReturnTuple(Box_Bool(value_ != 0));+}+ReturnTuple Value_Int::Call_asChar(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Int.asChar")+  return ReturnTuple(Box_Char(value_ % 0xff));+}+ReturnTuple Value_Int::Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Int.asFloat")+  return ReturnTuple(Box_Float(value_));+}+ReturnTuple Value_Int::Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Int.asInt")+  return ReturnTuple(Var_self);+}+ReturnTuple Value_Int::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("Int.formatted")+  std::ostringstream output;+  output << value_;+  return ReturnTuple(Box_String(output.str()));+}+}  // namespace+TypeCategory& GetCategory_Int() {+  return CreateCategory_Int();+}+TypeInstance& GetType_Int(Params<0>::Type params) {+  return CreateType_Int(params);+}+#ifdef ZEOLITE_DYNAMIC_NAMESPACE+}  // namespace ZEOLITE_DYNAMIC_NAMESPACE+using namespace ZEOLITE_DYNAMIC_NAMESPACE;+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+++S<TypeValue> Box_Int(PrimInt value) {+  return S_get(new Value_Int(CreateType_Int(Params<0>::Type()), value));+}
+ base/Category_String.cpp view
@@ -0,0 +1,245 @@+/* -----------------------------------------------------------------------------+Copyright 2019-2020 Kevin P. Barry++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.+----------------------------------------------------------------------------- */++// Author: Kevin P. Barry [ta0kira@gmail.com]++#include "Category_String.hpp"++#include <map>+#include <sstream>++#include "category-source.hpp"+#include "Category_AsBool.hpp"+#include "Category_Formatted.hpp"+#include "Category_ReadPosition.hpp"+#include "Category_Char.hpp"+#include "Category_Equals.hpp"+#include "Category_LessThan.hpp"+++#ifdef ZEOLITE_DYNAMIC_NAMESPACE+namespace ZEOLITE_DYNAMIC_NAMESPACE {+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+namespace {+const int collection_String = 0;+}  // namespace+const void* const Functions_String = &collection_String;+const ValueFunction& Function_String_subSequence = (*new ValueFunction{ 0, 2, 1, "String", "subSequence", Functions_String, 0 });+namespace {+class Category_String;+class Type_String;+Type_String& CreateType_String(Params<0>::Type params);+class Value_String;+S<TypeValue> CreateValue(Type_String& parent, const ParamTuple& params, const ValueTuple& args);+struct Category_String : public TypeCategory {+  std::string CategoryName() const final { return "String"; }+  Category_String() {+    CycleCheck<Category_String>::Check();+    CycleCheck<Category_String> marker(*this);+    TRACE_FUNCTION("String (init @category)")+  }+  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Category_String::*)(const ParamTuple&, const ValueTuple&);+    return TypeCategory::Dispatch(label, params, args);+  }+};+Category_String& CreateCategory_String() {+  static auto& category = *new Category_String();+  return category;+}+struct Type_String : public TypeInstance {+  std::string CategoryName() const final { return parent.CategoryName(); }+  void BuildTypeName(std::ostream& output) const final {+    return TypeInstance::TypeNameFrom(output, parent);+  }+  Category_String& parent;+  bool CanConvertFrom(const TypeInstance& from) const final {+    std::vector<const TypeInstance*> args;+    if (!from.TypeArgsForParent(parent, args)) return false;+    if(args.size() != 0) {+      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();+    }+    return true;+  }+  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {+    if (&category == &GetCategory_String()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_AsBool()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_Formatted()) {+      args = std::vector<const TypeInstance*>{};+      return true;+    }+    if (&category == &GetCategory_ReadPosition()) {+      args = std::vector<const TypeInstance*>{&GetType_Char(T_get())};+      return true;+    }+    return false;+  }+  Type_String(Category_String& p, Params<0>::Type params) : parent(p) {+    CycleCheck<Type_String>::Check();+    CycleCheck<Type_String> marker(*this);+    TRACE_FUNCTION("String (init @type)")+  }+  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {+    using CallType = ReturnTuple(Type_String::*)(const ParamTuple&, const ValueTuple&);+    static const CallType Table_Equals[] = {+      &Type_String::Call_equals,+    };+    static const CallType Table_LessThan[] = {+      &Type_String::Call_lessThan,+    };+    if (label.collection == Functions_Equals) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Equals[label.function_num])(params, args);+    }+    if (label.collection == Functions_LessThan) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_LessThan[label.function_num])(params, args);+    }+    return TypeInstance::Dispatch(label, params, args);+  }+  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_lessThan(const ParamTuple& params, const ValueTuple& args);+};+Type_String& CreateType_String(Params<0>::Type params) {+  static auto& cache = *new InstanceMap<0,Type_String>();+  auto& cached = cache[params];+  if (!cached) { cached = R_get(new Type_String(CreateCategory_String(), params)); }+  return *cached;+}+struct Value_String : public TypeValue {+  Value_String(Type_String& p, const PrimString& value) : parent(p), value_(value) {}+  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {+    using CallType = ReturnTuple(Value_String::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);+    static const CallType Table_AsBool[] = {+      &Value_String::Call_asBool,+    };+    static const CallType Table_Formatted[] = {+      &Value_String::Call_formatted,+    };+    static const CallType Table_ReadPosition[] = {+      &Value_String::Call_readPosition,+      &Value_String::Call_readSize,+      &Value_String::Call_subSequence,+    };+    static const CallType Table_String[] = {+      &Value_String::Call_subSequence,+    };+    if (label.collection == Functions_AsBool) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_AsBool[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_Formatted) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_Formatted[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_ReadPosition) {+      if (label.function_num < 0 || label.function_num >= 3) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_ReadPosition[label.function_num])(self, params, args);+    }+    if (label.collection == Functions_String) {+      if (label.function_num < 0 || label.function_num >= 1) {+        FAIL() << "Bad function call " << label;+      }+      return (this->*Table_String[label.function_num])(self, params, args);+    }+    return TypeValue::Dispatch(self, label, params, args);+  }+  std::string CategoryName() const final { return parent.CategoryName(); }+  const PrimString& AsString() const final { return value_; }+  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_readPosition(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_readSize(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  ReturnTuple Call_subSequence(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);+  Type_String& parent;+  const PrimString value_;+};+ReturnTuple Type_String::Call_equals(const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("String.equals")+  const S<TypeValue>& Var_arg1 = (args.At(0));+  const S<TypeValue>& Var_arg2 = (args.At(1));+  return ReturnTuple(Box_Bool(Var_arg1->AsString()==Var_arg2->AsString()));+}+ReturnTuple Type_String::Call_lessThan(const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("String.lessThan")+  const S<TypeValue>& Var_arg1 = (args.At(0));+  const S<TypeValue>& Var_arg2 = (args.At(1));+  return ReturnTuple(Box_Bool(Var_arg1->AsString()<Var_arg2->AsString()));+}+ReturnTuple Value_String::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("String.asBool")+  return ReturnTuple(Box_Bool(value_.size() != 0));+}+ReturnTuple Value_String::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("String.formatted")+  return ReturnTuple(Var_self);+}+ReturnTuple Value_String::Call_readPosition(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("String.readPosition")+  const PrimInt Var_arg1 = (args.At(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 Value_String::Call_readSize(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("String.readSize")+  return ReturnTuple(Box_Int(value_.size()));+}+ReturnTuple Value_String::Call_subSequence(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {+  TRACE_FUNCTION("String.subSequence")+  const PrimInt Var_arg1 = (args.At(0))->AsInt();+  const PrimInt Var_arg2 = (args.At(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)));+}+}  // namespace+TypeCategory& GetCategory_String() {+  return CreateCategory_String();+}+TypeInstance& GetType_String(Params<0>::Type params) {+  return CreateType_String(params);+}+#ifdef ZEOLITE_DYNAMIC_NAMESPACE+}  // namespace ZEOLITE_DYNAMIC_NAMESPACE+using namespace ZEOLITE_DYNAMIC_NAMESPACE;+#endif  // ZEOLITE_DYNAMIC_NAMESPACE+++S<TypeValue> Box_String(const PrimString& value) {+  return S_get(new Value_String(CreateType_String(Params<0>::Type()), value));+}
base/builtin.0rp view
@@ -36,25 +36,25 @@   defines LessThan<Char> } -concrete Int {+concrete Float {   refines AsBool-  refines AsChar   refines AsInt   refines AsFloat   refines Formatted -  defines Equals<Int>-  defines LessThan<Int>+  defines Equals<Float>+  defines LessThan<Float> } -concrete Float {+concrete Int {   refines AsBool+  refines AsChar   refines AsInt   refines AsFloat   refines Formatted -  defines Equals<Float>-  defines LessThan<Float>+  defines Equals<Int>+  defines LessThan<Int> }  concrete String {@@ -72,10 +72,6 @@   asBool () -> (Bool) } -@value interface AsInt {-  asInt () -> (Int)-}- @value interface AsChar {   asChar () -> (Char) }@@ -84,12 +80,8 @@   asFloat () -> (Float) } -@type interface LessThan<#x|> {-  lessThan (#x,#x) -> (Bool)-}--@type interface Equals<#x|> {-  equals (#x,#x) -> (Bool)+@value interface AsInt {+  asInt () -> (Int) }  @value interface Formatted {@@ -100,4 +92,12 @@   readPosition (Int) -> (#x)   readSize () -> (Int)   subSequence (Int,Int) -> (ReadPosition<#x>)+}++@type interface Equals<#x|> {+  equals (#x,#x) -> (Bool)+}++@type interface LessThan<#x|> {+  lessThan (#x,#x) -> (Bool) }
− base/builtin.cpp
@@ -1,1192 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2019-2020 Kevin P. Barry--Licensed under the Apache License, Version 2.0 (the "License");-you may not use this file except in compliance with the License.-You may obtain a copy of the License at--    http://www.apache.org/licenses/LICENSE-2.0--Unless required by applicable law or agreed to in writing, software-distributed under the License is distributed on an "AS IS" BASIS,-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.-See the License for the specific language governing permissions and-limitations under the License.------------------------------------------------------------------------------ */--// Author: Kevin P. Barry [ta0kira@gmail.com]--#include "builtin.hpp"--#include <map>-#include <sstream>--#include "category-source.hpp"-#include "Category_AsBool.hpp"-#include "Category_AsChar.hpp"-#include "Category_AsInt.hpp"-#include "Category_AsFloat.hpp"-#include "Category_Bool.hpp"-#include "Category_Char.hpp"-#include "Category_Equals.hpp"-#include "Category_Float.hpp"-#include "Category_Formatted.hpp"-#include "Category_Int.hpp"-#include "Category_LessThan.hpp"-#include "Category_ReadPosition.hpp"-#include "Category_String.hpp"---void BuiltinFail(const S<TypeValue>& formatted) {-  FAIL() << TypeValue::Call(formatted, Function_Formatted_formatted,-                            ParamTuple(), ArgTuple()).Only()->AsString();-  __builtin_unreachable();-}--namespace {--struct OptionalEmpty : public TypeValue {-  ReturnTuple Dispatch(const S<TypeValue>& self,-                       const ValueFunction& label,-                       const ParamTuple& params, const ValueTuple& args) final {-    FAIL() << "Function called on empty value";-    __builtin_unreachable();-  }--  std::string CategoryName() const final { return "empty"; }--  bool Present() const final { return false; }-};--struct Type_Intersect : public TypeInstance {-  Type_Intersect(L<TypeInstance*> params) : params_(params.begin(), params.end()) {}--  std::string CategoryName() const final { return "(intersection)"; }--  void BuildTypeName(std::ostream& output) const final {-    if (params_.empty()) {-      output << "any";-    } else {-      output << "[";-      bool first = true;-      for (const auto param : params_) {-        if (!first) output << "&";-        first = false;-        param->BuildTypeName(output);-      }-      output << "]";-    }-  }--  MergeType InstanceMergeType() const final-  { return MergeType::INTERSECT; }--  std::vector<const TypeInstance*> MergedTypes() const final-  { return params_; }--  const L<const TypeInstance*> params_;-};--struct Type_Union : public TypeInstance {-  Type_Union(L<TypeInstance*> params) : params_(params.begin(), params.end()) {}--  std::string CategoryName() const final { return "(union)"; }--  void BuildTypeName(std::ostream& output) const final {-    if (params_.empty()) {-      output << "all";-    } else {-      output << "[";-      bool first = true;-      for (const auto param : params_) {-        if (!first) output << "|";-        first = false;-        param->BuildTypeName(output);-      }-      output << "]";-    }-  }--  MergeType InstanceMergeType() const final-  { return MergeType::UNION; }--  std::vector<const TypeInstance*> MergedTypes() const final-  { return params_; }--  const L<const TypeInstance*> params_;-};--}  // namespace---TypeInstance& Merge_Intersect(L<TypeInstance*> params) {-  static auto& cache = *new std::map<L<TypeInstance*>,R<Type_Intersect>>();-  auto& cached = cache[params];-  if (!cached) { cached = R_get(new Type_Intersect(params)); }-  return *cached;-}--TypeInstance& Merge_Union(L<TypeInstance*> params) {-  static auto& cache = *new std::map<L<TypeInstance*>,R<Type_Union>>();-  auto& cached = cache[params];-  if (!cached) { cached = R_get(new Type_Union(params)); }-  return *cached;-}--TypeInstance& GetMerged_Any() {-  static auto& instance = Merge_Intersect(L_get<TypeInstance*>());-  return instance;-}--TypeInstance& GetMerged_All() {-  static auto& instance = Merge_Union(L_get<TypeInstance*>());-  return instance;-}---const S<TypeValue>& Var_empty = *new S<TypeValue>(new OptionalEmpty());---// Bool--#ifdef ZEOLITE_DYNAMIC_NAMESPACE-namespace ZEOLITE_DYNAMIC_NAMESPACE {-#endif  // ZEOLITE_DYNAMIC_NAMESPACE-namespace {-const int collection_Bool = 0;-}  // namespace-const void* const Functions_Bool = &collection_Bool;-namespace {-class Category_Bool;-class Type_Bool;-Type_Bool& CreateType_Bool(Params<0>::Type params);-class Value_Bool;-S<TypeValue> CreateValue(Type_Bool& parent, const ParamTuple& params, const ValueTuple& args);-struct Category_Bool : public TypeCategory {-  std::string CategoryName() const final { return "Bool"; }-  Category_Bool() {-    CycleCheck<Category_Bool>::Check();-    CycleCheck<Category_Bool> marker(*this);-    TRACE_FUNCTION("Bool (init @category)")-  }-  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Category_Bool::*)(const ParamTuple&, const ValueTuple&);-    return TypeCategory::Dispatch(label, params, args);-  }-};-Category_Bool& CreateCategory_Bool() {-  static auto& category = *new Category_Bool();-  return category;-}-struct Type_Bool : public TypeInstance {-  std::string CategoryName() const final { return parent.CategoryName(); }-  void BuildTypeName(std::ostream& output) const final {-    return TypeInstance::TypeNameFrom(output, parent);-  }-  Category_Bool& parent;-  bool CanConvertFrom(const TypeInstance& from) const final {-    std::vector<const TypeInstance*> args;-    if (!from.TypeArgsForParent(parent, args)) return false;-    if(args.size() != 0) {-      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();-    }-    return true;-  }-  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {-    if (&category == &GetCategory_Bool()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsBool()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsInt()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsFloat()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_Formatted()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    return false;-  }-  Type_Bool(Category_Bool& p, Params<0>::Type params) : parent(p) {-    CycleCheck<Type_Bool>::Check();-    CycleCheck<Type_Bool> marker(*this);-    TRACE_FUNCTION("Bool (init @type)")-  }-  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Type_Bool::*)(const ParamTuple&, const ValueTuple&);-    static const CallType Table_Equals[] = {-      &Type_Bool::Call_equals,-    };-    if (label.collection == Functions_Equals) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Equals[label.function_num])(params, args);-    }-    return TypeInstance::Dispatch(label, params, args);-  }-  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);-};-Type_Bool& CreateType_Bool(Params<0>::Type params) {-  static auto& cache = *new InstanceMap<0,Type_Bool>();-  auto& cached = cache[params];-  if (!cached) { cached = R_get(new Type_Bool(CreateCategory_Bool(), params)); }-  return *cached;-}-struct Value_Bool : public TypeValue {-  Value_Bool(Type_Bool& p, bool value) : parent(p), value_(value) {}-  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {-    using CallType = ReturnTuple(Value_Bool::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);-    static const CallType Table_AsBool[] = {-      &Value_Bool::Call_asBool,-    };-    static const CallType Table_AsFloat[] = {-      &Value_Bool::Call_asFloat,-    };-    static const CallType Table_AsInt[] = {-      &Value_Bool::Call_asInt,-    };-    static const CallType Table_Formatted[] = {-      &Value_Bool::Call_formatted,-    };-    if (label.collection == Functions_AsBool) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsBool[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsFloat) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsFloat[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsInt) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsInt[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_Formatted) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Formatted[label.function_num])(self, params, args);-    }-    return TypeValue::Dispatch(self, label, params, args);-  }-  std::string CategoryName() const final { return parent.CategoryName(); }-  bool AsBool() const final { return value_; }-  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  Type_Bool& parent;-  const bool value_;-};-ReturnTuple Type_Bool::Call_equals(const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Bool.equals")-  const bool Var_arg1 = (args.At(0))->AsBool();-  const bool Var_arg2 = (args.At(1))->AsBool();-  return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));-}-ReturnTuple Value_Bool::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Bool.asBool")-  return ReturnTuple(Var_self);-}-ReturnTuple Value_Bool::Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Bool.asFloat")-  return ReturnTuple(Box_Float(value_ ? 1.0 : 0.0));-}-ReturnTuple Value_Bool::Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Bool.asInt")-  return ReturnTuple(Box_Int(value_? 1 : 0));-}-ReturnTuple Value_Bool::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Bool.formatted")-  return ReturnTuple(Box_String(value_? "true" : "false"));-}-const S<TypeValue>& Var_true = *new S<TypeValue>(new Value_Bool(CreateType_Bool(Params<0>::Type()), true));-const S<TypeValue>& Var_false = *new S<TypeValue>(new Value_Bool(CreateType_Bool(Params<0>::Type()), false));-}  // namespace-TypeCategory& GetCategory_Bool() {-  return CreateCategory_Bool();-}-TypeInstance& GetType_Bool(Params<0>::Type params) {-  return CreateType_Bool(params);-}-#ifdef ZEOLITE_DYNAMIC_NAMESPACE-}  // namespace ZEOLITE_DYNAMIC_NAMESPACE-using namespace ZEOLITE_DYNAMIC_NAMESPACE;-#endif  // ZEOLITE_DYNAMIC_NAMESPACE---// Char--#ifdef ZEOLITE_DYNAMIC_NAMESPACE-namespace ZEOLITE_DYNAMIC_NAMESPACE {-#endif  // ZEOLITE_DYNAMIC_NAMESPACE-namespace {-const int collection_Char = 0;-}  // namespace-const void* const Functions_Char = &collection_Char;-namespace {-class Category_Char;-class Type_Char;-Type_Char& CreateType_Char(Params<0>::Type params);-class Value_Char;-S<TypeValue> CreateValue(Type_Char& parent, const ParamTuple& params, const ValueTuple& args);-struct Category_Char : public TypeCategory {-  std::string CategoryName() const final { return "Char"; }-  Category_Char() {-    CycleCheck<Category_Char>::Check();-    CycleCheck<Category_Char> marker(*this);-    TRACE_FUNCTION("Char (init @category)")-  }-  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Category_Char::*)(const ParamTuple&, const ValueTuple&);-    return TypeCategory::Dispatch(label, params, args);-  }-};-Category_Char& CreateCategory_Char() {-  static auto& category = *new Category_Char();-  return category;-}-struct Type_Char : public TypeInstance {-  std::string CategoryName() const final { return parent.CategoryName(); }-  void BuildTypeName(std::ostream& output) const final {-    return TypeInstance::TypeNameFrom(output, parent);-  }-  Category_Char& parent;-  bool CanConvertFrom(const TypeInstance& from) const final {-    std::vector<const TypeInstance*> args;-    if (!from.TypeArgsForParent(parent, args)) return false;-    if(args.size() != 0) {-      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();-    }-    return true;-  }-  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {-    if (&category == &GetCategory_Char()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsBool()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsChar()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsInt()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsFloat()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_Formatted()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    return false;-  }-  Type_Char(Category_Char& p, Params<0>::Type params) : parent(p) {-    CycleCheck<Type_Char>::Check();-    CycleCheck<Type_Char> marker(*this);-    TRACE_FUNCTION("Char (init @type)")-  }-  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Type_Char::*)(const ParamTuple&, const ValueTuple&);-    static const CallType Table_Equals[] = {-      &Type_Char::Call_equals,-    };-    static const CallType Table_LessThan[] = {-      &Type_Char::Call_lessThan,-    };-    if (label.collection == Functions_Equals) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Equals[label.function_num])(params, args);-    }-    if (label.collection == Functions_LessThan) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_LessThan[label.function_num])(params, args);-    }-    return TypeInstance::Dispatch(label, params, args);-  }-  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_lessThan(const ParamTuple& params, const ValueTuple& args);-};-Type_Char& CreateType_Char(Params<0>::Type params) {-  static auto& cache = *new InstanceMap<0,Type_Char>();-  auto& cached = cache[params];-  if (!cached) { cached = R_get(new Type_Char(CreateCategory_Char(), params)); }-  return *cached;-}-struct Value_Char : public TypeValue {-  Value_Char(Type_Char& p, PrimChar value) : parent(p), value_(value) {}-  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {-    using CallType = ReturnTuple(Value_Char::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);-    static const CallType Table_AsBool[] = {-      &Value_Char::Call_asBool,-    };-    static const CallType Table_AsChar[] = {-      &Value_Char::Call_asChar,-    };-    static const CallType Table_AsFloat[] = {-      &Value_Char::Call_asFloat,-    };-    static const CallType Table_AsInt[] = {-      &Value_Char::Call_asInt,-    };-    static const CallType Table_Formatted[] = {-      &Value_Char::Call_formatted,-    };-    if (label.collection == Functions_AsBool) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsBool[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsChar) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsChar[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsFloat) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsFloat[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsInt) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsInt[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_Formatted) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Formatted[label.function_num])(self, params, args);-    }-    return TypeValue::Dispatch(self, label, params, args);-  }-  std::string CategoryName() const final { return parent.CategoryName(); }-  PrimChar AsChar() const final { return value_; }-  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asChar(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  Type_Char& parent;-  const PrimChar value_;-};-ReturnTuple Type_Char::Call_equals(const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Char.equals")-  const PrimChar Var_arg1 = (args.At(0))->AsChar();-  const PrimChar Var_arg2 = (args.At(1))->AsChar();-      return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));-}-ReturnTuple Type_Char::Call_lessThan(const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Char.lessThan")-  const PrimChar Var_arg1 = (args.At(0))->AsChar();-  const PrimChar Var_arg2 = (args.At(1))->AsChar();-  return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));-}-ReturnTuple Value_Char::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Char.asBool")-  return ReturnTuple(Box_Bool(value_ != '\0'));-}-ReturnTuple Value_Char::Call_asChar(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Char.asChar")-  return ReturnTuple(Var_self);-}-ReturnTuple Value_Char::Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Char.asFloat")-  return ReturnTuple(Box_Float(value_));-}-ReturnTuple Value_Char::Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Char.asInt")-  return ReturnTuple(Box_Int(value_));-}-ReturnTuple Value_Char::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Char.formatted")-  std::ostringstream output;-  output << value_;-  return ReturnTuple(Box_String(output.str()));-}-}  // namespace-TypeCategory& GetCategory_Char() {-  return CreateCategory_Char();-}-TypeInstance& GetType_Char(Params<0>::Type params) {-  return CreateType_Char(params);-}-#ifdef ZEOLITE_DYNAMIC_NAMESPACE-}  // namespace ZEOLITE_DYNAMIC_NAMESPACE-using namespace ZEOLITE_DYNAMIC_NAMESPACE;-#endif  // ZEOLITE_DYNAMIC_NAMESPACE---// Int--#ifdef ZEOLITE_DYNAMIC_NAMESPACE-namespace ZEOLITE_DYNAMIC_NAMESPACE {-#endif  // ZEOLITE_DYNAMIC_NAMESPACE-namespace {-const int collection_Int = 0;-}  // namespace-const void* const Functions_Int = &collection_Int;-namespace {-class Category_Int;-class Type_Int;-Type_Int& CreateType_Int(Params<0>::Type params);-class Value_Int;-S<TypeValue> CreateValue(Type_Int& parent, const ParamTuple& params, const ValueTuple& args);-struct Category_Int : public TypeCategory {-  std::string CategoryName() const final { return "Int"; }-  Category_Int() {-    CycleCheck<Category_Int>::Check();-    CycleCheck<Category_Int> marker(*this);-    TRACE_FUNCTION("Int (init @category)")-  }-  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Category_Int::*)(const ParamTuple&, const ValueTuple&);-    return TypeCategory::Dispatch(label, params, args);-  }-};-Category_Int& CreateCategory_Int() {-  static auto& category = *new Category_Int();-  return category;-}-struct Type_Int : public TypeInstance {-  std::string CategoryName() const final { return parent.CategoryName(); }-  void BuildTypeName(std::ostream& output) const final {-    return TypeInstance::TypeNameFrom(output, parent);-  }-  Category_Int& parent;-  bool CanConvertFrom(const TypeInstance& from) const final {-    std::vector<const TypeInstance*> args;-    if (!from.TypeArgsForParent(parent, args)) return false;-    if(args.size() != 0) {-      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();-    }-    return true;-  }-  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {-    if (&category == &GetCategory_Int()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsBool()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsChar()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsInt()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsFloat()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_Formatted()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    return false;-  }-  Type_Int(Category_Int& p, Params<0>::Type params) : parent(p) {-    CycleCheck<Type_Int>::Check();-    CycleCheck<Type_Int> marker(*this);-    TRACE_FUNCTION("Int (init @type)")-  }-  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Type_Int::*)(const ParamTuple&, const ValueTuple&);-    static const CallType Table_Equals[] = {-      &Type_Int::Call_equals,-    };-    static const CallType Table_LessThan[] = {-      &Type_Int::Call_lessThan,-    };-    if (label.collection == Functions_Equals) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Equals[label.function_num])(params, args);-    }-    if (label.collection == Functions_LessThan) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_LessThan[label.function_num])(params, args);-    }-    return TypeInstance::Dispatch(label, params, args);-  }-  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_lessThan(const ParamTuple& params, const ValueTuple& args);-};-Type_Int& CreateType_Int(Params<0>::Type params) {-  static auto& cache = *new InstanceMap<0,Type_Int>();-  auto& cached = cache[params];-  if (!cached) { cached = R_get(new Type_Int(CreateCategory_Int(), params)); }-  return *cached;-}-struct Value_Int : public TypeValue {-  Value_Int(Type_Int& p, PrimInt value) : parent(p), value_(value) {}-  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {-    using CallType = ReturnTuple(Value_Int::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);-    static const CallType Table_AsBool[] = {-      &Value_Int::Call_asBool,-    };-    static const CallType Table_AsChar[] = {-      &Value_Int::Call_asChar,-    };-    static const CallType Table_AsFloat[] = {-      &Value_Int::Call_asFloat,-    };-    static const CallType Table_AsInt[] = {-      &Value_Int::Call_asInt,-    };-    static const CallType Table_Formatted[] = {-      &Value_Int::Call_formatted,-    };-    if (label.collection == Functions_AsBool) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsBool[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsChar) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsChar[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsFloat) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsFloat[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsInt) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsInt[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_Formatted) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Formatted[label.function_num])(self, params, args);-    }-    return TypeValue::Dispatch(self, label, params, args);-  }-  std::string CategoryName() const final { return parent.CategoryName(); }-  PrimInt AsInt() const final { return value_; }-  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asChar(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  Type_Int& parent;-  const PrimInt value_;-};-ReturnTuple Type_Int::Call_equals(const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Int.equals")-  const PrimInt Var_arg1 = (args.At(0))->AsInt();-  const PrimInt Var_arg2 = (args.At(1))->AsInt();-  return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));-}-ReturnTuple Type_Int::Call_lessThan(const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Int.lessThan")-  const PrimInt Var_arg1 = (args.At(0))->AsInt();-  const PrimInt Var_arg2 = (args.At(1))->AsInt();-  return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));-}-ReturnTuple Value_Int::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Int.asBool")-  return ReturnTuple(Box_Bool(value_ != 0));-}-ReturnTuple Value_Int::Call_asChar(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Int.asChar")-  return ReturnTuple(Box_Char(value_ % 0xff));-}-ReturnTuple Value_Int::Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Int.asFloat")-  return ReturnTuple(Box_Float(value_));-}-ReturnTuple Value_Int::Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Int.asInt")-  return ReturnTuple(Var_self);-}-ReturnTuple Value_Int::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Int.formatted")-  std::ostringstream output;-  output << value_;-  return ReturnTuple(Box_String(output.str()));-}-}  // namespace-TypeCategory& GetCategory_Int() {-  return CreateCategory_Int();-}-TypeInstance& GetType_Int(Params<0>::Type params) {-  return CreateType_Int(params);-}-#ifdef ZEOLITE_DYNAMIC_NAMESPACE-}  // namespace ZEOLITE_DYNAMIC_NAMESPACE-using namespace ZEOLITE_DYNAMIC_NAMESPACE;-#endif  // ZEOLITE_DYNAMIC_NAMESPACE---// Float--#ifdef ZEOLITE_DYNAMIC_NAMESPACE-namespace ZEOLITE_DYNAMIC_NAMESPACE {-#endif  // ZEOLITE_DYNAMIC_NAMESPACE-namespace {-const int collection_Float = 0;-}  // namespace-const void* const Functions_Float = &collection_Float;-namespace {-class Category_Float;-class Type_Float;-Type_Float& CreateType_Float(Params<0>::Type params);-class Value_Float;-S<TypeValue> CreateValue(Type_Float& parent, const ParamTuple& params, const ValueTuple& args);-struct Category_Float : public TypeCategory {-  std::string CategoryName() const final { return "Float"; }-  Category_Float() {-    CycleCheck<Category_Float>::Check();-    CycleCheck<Category_Float> marker(*this);-    TRACE_FUNCTION("Float (init @category)")-  }-  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Category_Float::*)(const ParamTuple&, const ValueTuple&);-    return TypeCategory::Dispatch(label, params, args);-  }-};-Category_Float& CreateCategory_Float() {-  static auto& category = *new Category_Float();-  return category;-}-struct Type_Float : public TypeInstance {-  std::string CategoryName() const final { return parent.CategoryName(); }-  void BuildTypeName(std::ostream& output) const final {-    return TypeInstance::TypeNameFrom(output, parent);-  }-  Category_Float& parent;-  bool CanConvertFrom(const TypeInstance& from) const final {-    std::vector<const TypeInstance*> args;-    if (!from.TypeArgsForParent(parent, args)) return false;-    if(args.size() != 0) {-      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();-    }-    return true;-  }-  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {-    if (&category == &GetCategory_Float()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsBool()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsInt()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsFloat()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_Formatted()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    return false;-  }-  Type_Float(Category_Float& p, Params<0>::Type params) : parent(p) {-    CycleCheck<Type_Float>::Check();-    CycleCheck<Type_Float> marker(*this);-    TRACE_FUNCTION("Float (init @type)")-  }-  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Type_Float::*)(const ParamTuple&, const ValueTuple&);-    static const CallType Table_Equals[] = {-      &Type_Float::Call_equals,-    };-    static const CallType Table_LessThan[] = {-      &Type_Float::Call_lessThan,-    };-    if (label.collection == Functions_Equals) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Equals[label.function_num])(params, args);-    }-    if (label.collection == Functions_LessThan) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_LessThan[label.function_num])(params, args);-    }-    return TypeInstance::Dispatch(label, params, args);-  }-  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_lessThan(const ParamTuple& params, const ValueTuple& args);-};-Type_Float& CreateType_Float(Params<0>::Type params) {-  static auto& cache = *new InstanceMap<0,Type_Float>();-  auto& cached = cache[params];-  if (!cached) { cached = R_get(new Type_Float(CreateCategory_Float(), params)); }-  return *cached;-}-struct Value_Float : public TypeValue {-  Value_Float(Type_Float& p, PrimFloat value) : parent(p), value_(value) {}-  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {-    using CallType = ReturnTuple(Value_Float::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);-    static const CallType Table_AsBool[] = {-      &Value_Float::Call_asBool,-    };-    static const CallType Table_AsFloat[] = {-      &Value_Float::Call_asFloat,-    };-    static const CallType Table_AsInt[] = {-      &Value_Float::Call_asInt,-    };-    static const CallType Table_Formatted[] = {-      &Value_Float::Call_formatted,-    };-    if (label.collection == Functions_AsBool) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsBool[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsFloat) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsFloat[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_AsInt) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsInt[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_Formatted) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Formatted[label.function_num])(self, params, args);-    }-    return TypeValue::Dispatch(self, label, params, args);-  }-  std::string CategoryName() const final { return parent.CategoryName(); }-  PrimFloat AsFloat() const final { return value_; }-  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  Type_Float& parent;-  const PrimFloat value_;-};-ReturnTuple Type_Float::Call_equals(const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Float.equals")-  const PrimFloat Var_arg1 = (args.At(0))->AsFloat();-  const PrimFloat Var_arg2 = (args.At(1))->AsFloat();-  return ReturnTuple(Box_Bool(Var_arg1==Var_arg2));-}-ReturnTuple Type_Float::Call_lessThan(const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Float.lessThan")-  const PrimFloat Var_arg1 = (args.At(0))->AsFloat();-  const PrimFloat Var_arg2 = (args.At(1))->AsFloat();-  return ReturnTuple(Box_Bool(Var_arg1<Var_arg2));-}-ReturnTuple Value_Float::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Float.asBool")-  return ReturnTuple(Box_Bool(value_ != 0.0));-}-ReturnTuple Value_Float::Call_asFloat(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Float.asFloat")-  return ReturnTuple(Var_self);-}-ReturnTuple Value_Float::Call_asInt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Float.asInt")-  return ReturnTuple(Box_Int(value_));-}-ReturnTuple Value_Float::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("Float.formatted")-  std::ostringstream output;-  output << value_;-  return ReturnTuple(Box_String(output.str()));-}-}  // namespace-TypeCategory& GetCategory_Float() {-  return CreateCategory_Float();-}-TypeInstance& GetType_Float(Params<0>::Type params) {-  return CreateType_Float(params);-}-#ifdef ZEOLITE_DYNAMIC_NAMESPACE-}  // namespace ZEOLITE_DYNAMIC_NAMESPACE-using namespace ZEOLITE_DYNAMIC_NAMESPACE;-#endif  // ZEOLITE_DYNAMIC_NAMESPACE---// String--#ifdef ZEOLITE_DYNAMIC_NAMESPACE-namespace ZEOLITE_DYNAMIC_NAMESPACE {-#endif  // ZEOLITE_DYNAMIC_NAMESPACE-namespace {-const int collection_String = 0;-}  // namespace-const void* const Functions_String = &collection_String;-const ValueFunction& Function_String_subSequence = (*new ValueFunction{ 0, 2, 1, "String", "subSequence", Functions_String, 0 });-namespace {-class Category_String;-class Type_String;-Type_String& CreateType_String(Params<0>::Type params);-class Value_String;-S<TypeValue> CreateValue(Type_String& parent, const ParamTuple& params, const ValueTuple& args);-struct Category_String : public TypeCategory {-  std::string CategoryName() const final { return "String"; }-  Category_String() {-    CycleCheck<Category_String>::Check();-    CycleCheck<Category_String> marker(*this);-    TRACE_FUNCTION("String (init @category)")-  }-  ReturnTuple Dispatch(const CategoryFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Category_String::*)(const ParamTuple&, const ValueTuple&);-    return TypeCategory::Dispatch(label, params, args);-  }-};-Category_String& CreateCategory_String() {-  static auto& category = *new Category_String();-  return category;-}-struct Type_String : public TypeInstance {-  std::string CategoryName() const final { return parent.CategoryName(); }-  void BuildTypeName(std::ostream& output) const final {-    return TypeInstance::TypeNameFrom(output, parent);-  }-  Category_String& parent;-  bool CanConvertFrom(const TypeInstance& from) const final {-    std::vector<const TypeInstance*> args;-    if (!from.TypeArgsForParent(parent, args)) return false;-    if(args.size() != 0) {-      FAIL() << "Wrong number of args (" << args.size() << ")  for " << CategoryName();-    }-    return true;-  }-  bool TypeArgsForParent(const TypeCategory& category, std::vector<const TypeInstance*>& args) const final {-    if (&category == &GetCategory_String()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_AsBool()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_Formatted()) {-      args = std::vector<const TypeInstance*>{};-      return true;-    }-    if (&category == &GetCategory_ReadPosition()) {-      args = std::vector<const TypeInstance*>{&GetType_Char(T_get())};-      return true;-    }-    return false;-  }-  Type_String(Category_String& p, Params<0>::Type params) : parent(p) {-    CycleCheck<Type_String>::Check();-    CycleCheck<Type_String> marker(*this);-    TRACE_FUNCTION("String (init @type)")-  }-  ReturnTuple Dispatch(const TypeFunction& label, const ParamTuple& params, const ValueTuple& args) final {-    using CallType = ReturnTuple(Type_String::*)(const ParamTuple&, const ValueTuple&);-    static const CallType Table_Equals[] = {-      &Type_String::Call_equals,-    };-    static const CallType Table_LessThan[] = {-      &Type_String::Call_lessThan,-    };-    if (label.collection == Functions_Equals) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Equals[label.function_num])(params, args);-    }-    if (label.collection == Functions_LessThan) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_LessThan[label.function_num])(params, args);-    }-    return TypeInstance::Dispatch(label, params, args);-  }-  ReturnTuple Call_equals(const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_lessThan(const ParamTuple& params, const ValueTuple& args);-};-Type_String& CreateType_String(Params<0>::Type params) {-  static auto& cache = *new InstanceMap<0,Type_String>();-  auto& cached = cache[params];-  if (!cached) { cached = R_get(new Type_String(CreateCategory_String(), params)); }-  return *cached;-}-struct Value_String : public TypeValue {-  Value_String(Type_String& p, const PrimString& value) : parent(p), value_(value) {}-  ReturnTuple Dispatch(const S<TypeValue>& self, const ValueFunction& label, const ParamTuple& params,const ValueTuple& args) final {-    using CallType = ReturnTuple(Value_String::*)(const S<TypeValue>&, const ParamTuple&, const ValueTuple&);-    static const CallType Table_AsBool[] = {-      &Value_String::Call_asBool,-    };-    static const CallType Table_Formatted[] = {-      &Value_String::Call_formatted,-    };-    static const CallType Table_ReadPosition[] = {-      &Value_String::Call_readPosition,-      &Value_String::Call_readSize,-      &Value_String::Call_subSequence,-    };-    static const CallType Table_String[] = {-      &Value_String::Call_subSequence,-    };-    if (label.collection == Functions_AsBool) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_AsBool[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_Formatted) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_Formatted[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_ReadPosition) {-      if (label.function_num < 0 || label.function_num >= 3) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_ReadPosition[label.function_num])(self, params, args);-    }-    if (label.collection == Functions_String) {-      if (label.function_num < 0 || label.function_num >= 1) {-        FAIL() << "Bad function call " << label;-      }-      return (this->*Table_String[label.function_num])(self, params, args);-    }-    return TypeValue::Dispatch(self, label, params, args);-  }-  std::string CategoryName() const final { return parent.CategoryName(); }-  const PrimString& AsString() const final { return value_; }-  ReturnTuple Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_readPosition(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_readSize(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  ReturnTuple Call_subSequence(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args);-  Type_String& parent;-  const PrimString value_;-};-ReturnTuple Type_String::Call_equals(const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("String.equals")-  const S<TypeValue>& Var_arg1 = (args.At(0));-  const S<TypeValue>& Var_arg2 = (args.At(1));-  return ReturnTuple(Box_Bool(Var_arg1->AsString()==Var_arg2->AsString()));-}-ReturnTuple Type_String::Call_lessThan(const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("String.lessThan")-  const S<TypeValue>& Var_arg1 = (args.At(0));-  const S<TypeValue>& Var_arg2 = (args.At(1));-  return ReturnTuple(Box_Bool(Var_arg1->AsString()<Var_arg2->AsString()));-}-ReturnTuple Value_String::Call_asBool(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("String.asBool")-  return ReturnTuple(Box_Bool(value_.size() != 0));-}-ReturnTuple Value_String::Call_formatted(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("String.formatted")-  return ReturnTuple(Var_self);-}-ReturnTuple Value_String::Call_readPosition(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("String.readPosition")-  const PrimInt Var_arg1 = (args.At(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 Value_String::Call_readSize(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("String.readSize")-  return ReturnTuple(Box_Int(value_.size()));-}-ReturnTuple Value_String::Call_subSequence(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) {-  TRACE_FUNCTION("String.subSequence")-  const PrimInt Var_arg1 = (args.At(0))->AsInt();-  const PrimInt Var_arg2 = (args.At(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)));-}-}  // namespace-TypeCategory& GetCategory_String() {-  return CreateCategory_String();-}-TypeInstance& GetType_String(Params<0>::Type params) {-  return CreateType_String(params);-}-#ifdef ZEOLITE_DYNAMIC_NAMESPACE-}  // namespace ZEOLITE_DYNAMIC_NAMESPACE-using namespace ZEOLITE_DYNAMIC_NAMESPACE;-#endif  // ZEOLITE_DYNAMIC_NAMESPACE---S<TypeValue> Box_Bool(bool value) {-  return value? Var_true : Var_false;-}--S<TypeValue> Box_Char(PrimChar value) {-  return S_get(new Value_Char(CreateType_Char(Params<0>::Type()), value));-}--S<TypeValue> Box_Int(PrimInt value) {-  return S_get(new Value_Int(CreateType_Int(Params<0>::Type()), value));-}--S<TypeValue> Box_Float(PrimFloat value) {-  return S_get(new Value_Float(CreateType_Float(Params<0>::Type()), value));-}--S<TypeValue> Box_String(const PrimString& value) {-  return S_get(new Value_String(CreateType_String(Params<0>::Type()), value));-}
− base/builtin.hpp
@@ -1,41 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2019-2020 Kevin P. Barry--Licensed under the Apache License, Version 2.0 (the "License");-you may not use this file except in compliance with the License.-You may obtain a copy of the License at--    http://www.apache.org/licenses/LICENSE-2.0--Unless required by applicable law or agreed to in writing, software-distributed under the License is distributed on an "AS IS" BASIS,-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.-See the License for the specific language governing permissions and-limitations under the License.------------------------------------------------------------------------------ */--// Author: Kevin P. Barry [ta0kira@gmail.com]--#ifndef BUILTIN_HPP_-#define BUILTIN_HPP_--#include "category-header.hpp"---void BuiltinFail(const S<TypeValue>& formatted) __attribute__ ((noreturn));--TypeInstance& Merge_Intersect(L<TypeInstance*> params);-TypeInstance& Merge_Union(L<TypeInstance*> params);--TypeInstance& GetMerged_Any();-TypeInstance& GetMerged_All();--S<TypeValue> Box_Bool(bool value);-S<TypeValue> Box_String(const PrimString& value);-S<TypeValue> Box_Char(PrimChar value);-S<TypeValue> Box_Int(PrimInt value);-S<TypeValue> Box_Float(PrimFloat value);--extern const S<TypeValue>& Var_empty;--#endif  // BUILTIN_HPP_
base/category-header.hpp view
@@ -31,4 +31,12 @@ class TypeFunction; class ValueFunction; +TypeInstance& Merge_Intersect(L<TypeInstance*> params);+TypeInstance& Merge_Union(L<TypeInstance*> params);++TypeInstance& GetMerged_Any();+TypeInstance& GetMerged_All();++extern const S<TypeValue>& Var_empty;+ #endif  // CATEGORY_HEADER_HPP_
base/category-source.cpp view
@@ -19,7 +19,110 @@ #include "category-source.hpp"  #include "logging.hpp"-#include "builtin.hpp"+++namespace {++struct OptionalEmpty : public TypeValue {+  ReturnTuple Dispatch(const S<TypeValue>& self,+                       const ValueFunction& label,+                       const ParamTuple& params, const ValueTuple& args) final {+    FAIL() << "Function called on empty value";+    __builtin_unreachable();+  }++  std::string CategoryName() const final { return "empty"; }++  bool Present() const final { return false; }+};++struct Type_Intersect : public TypeInstance {+  Type_Intersect(L<TypeInstance*> params) : params_(params.begin(), params.end()) {}++  std::string CategoryName() const final { return "(intersection)"; }++  void BuildTypeName(std::ostream& output) const final {+    if (params_.empty()) {+      output << "any";+    } else {+      output << "[";+      bool first = true;+      for (const auto param : params_) {+        if (!first) output << "&";+        first = false;+        param->BuildTypeName(output);+      }+      output << "]";+    }+  }++  MergeType InstanceMergeType() const final+  { return MergeType::INTERSECT; }++  std::vector<const TypeInstance*> MergedTypes() const final+  { return params_; }++  const L<const TypeInstance*> params_;+};++struct Type_Union : public TypeInstance {+  Type_Union(L<TypeInstance*> params) : params_(params.begin(), params.end()) {}++  std::string CategoryName() const final { return "(union)"; }++  void BuildTypeName(std::ostream& output) const final {+    if (params_.empty()) {+      output << "all";+    } else {+      output << "[";+      bool first = true;+      for (const auto param : params_) {+        if (!first) output << "|";+        first = false;+        param->BuildTypeName(output);+      }+      output << "]";+    }+  }++  MergeType InstanceMergeType() const final+  { return MergeType::UNION; }++  std::vector<const TypeInstance*> MergedTypes() const final+  { return params_; }++  const L<const TypeInstance*> params_;+};++}  // namespace+++TypeInstance& Merge_Intersect(L<TypeInstance*> params) {+  static auto& cache = *new std::map<L<TypeInstance*>,R<Type_Intersect>>();+  auto& cached = cache[params];+  if (!cached) { cached = R_get(new Type_Intersect(params)); }+  return *cached;+}++TypeInstance& Merge_Union(L<TypeInstance*> params) {+  static auto& cache = *new std::map<L<TypeInstance*>,R<Type_Union>>();+  auto& cached = cache[params];+  if (!cached) { cached = R_get(new Type_Union(params)); }+  return *cached;+}++TypeInstance& GetMerged_Any() {+  static auto& instance = Merge_Intersect(L_get<TypeInstance*>());+  return instance;+}++TypeInstance& GetMerged_All() {+  static auto& instance = Merge_Union(L_get<TypeInstance*>());+  return instance;+}+++const S<TypeValue>& Var_empty = *new S<TypeValue>(new OptionalEmpty());   ReturnTuple TypeCategory::Dispatch(const CategoryFunction& label,
base/category-source.hpp view
@@ -25,9 +25,23 @@  #include "types.hpp" #include "function.hpp"-#include "builtin.hpp" #include "argv.hpp" #include "cycle-check.hpp"+++#define BUILTIN_FAIL(e) { \+  FAIL() << TypeValue::Call((e), Function_Formatted_formatted, \+                            ParamTuple(), ArgTuple()).Only()->AsString(); \+  __builtin_unreachable(); \+  }++extern const S<TypeValue>& Var_empty;++S<TypeValue> Box_Bool(bool value);+S<TypeValue> Box_String(const PrimString& value);+S<TypeValue> Box_Char(PrimChar value);+S<TypeValue> Box_Int(PrimInt value);+S<TypeValue> Box_Float(PrimFloat value);   class TypeCategory {
+ base/thread-capture.h view
@@ -0,0 +1,217 @@+/* -----------------------------------------------------------------------------+Copyright 2017 Google Inc.++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] [kevinbarry@google.com]++#ifndef THREAD_CAPTURE_H_+#define THREAD_CAPTURE_H_++#include <cassert>++#include "thread-crosser.h"++namespace capture_thread {++// Base class for instrumentation classes that need to be made available within+// a single thread, and possibly shared across threads. Derive a new class Type+// from ThreadCapture<Type> to define a new instrumentation type. Scoping is+// managed by adding a ScopedCapture *or* an AutoThreadCrosser member to+// instantiable implementations of the instrumentation. (If Type is abstract,+// add the member to the instantiable subclasses.) See ThreadCrosser for info+// about *automatic* sharing across threads, and ThreadBridge (below) for info+// about *manually* sharing across threads.+template <class Type>+class ThreadCapture {+ protected:+  ThreadCapture() = default;+  virtual ~ThreadCapture() = default;++  class CrossThreads;++  // Manages scoping of instrumentation within a single thread. Use ThreadBridge+  // + CrossThreads to share instrumentation across threads. Alternatively, use+  // AutoThreadCrosser *instead* of ScopedCapture to allow ThreadCrosser to+  // handle this automatically.+  class ScopedCapture {+   public:+    explicit inline ScopedCapture(Type* capture)+        : previous_(GetCurrent()), current_(capture) {+      SetCurrent(current_);+    }++    inline ~ScopedCapture() { SetCurrent(Previous()); }++    inline Type* Previous() const { return previous_; }++   private:+    ScopedCapture(const ScopedCapture&) = delete;+    ScopedCapture(ScopedCapture&&) = delete;+    ScopedCapture& operator=(const ScopedCapture&) = delete;+    ScopedCapture& operator=(ScopedCapture&&) = delete;+    void* operator new(std::size_t size) = delete;++    friend class CrossThreads;+    Type* const previous_;+    Type* const current_;+  };++  // Creates a bridge point for sharing a single type of instrumentation between+  // threads. Create this in the main thread, then enable crossing in the worker+  // thread with CrossThreads. This is only needed if the instrumentation uses+  // ScopedCapture instead of AutoThreadCrosser.+  //+  // NOTE: This isn't visible by default. If you want to make this functionality+  // available for a specific instrumentation class, add the following with+  // public visibility within the instrumentation class:+  //+  //   using ThreadCapture<Type>::ThreadBridge;+  class ThreadBridge {+   public:+    inline ThreadBridge() : capture_(GetCurrent()) {}++   private:+    ThreadBridge(const ThreadBridge&) = delete;+    ThreadBridge(ThreadBridge&&) = delete;+    ThreadBridge& operator=(const ThreadBridge&) = delete;+    ThreadBridge& operator=(ThreadBridge&&) = delete;+    void* operator new(std::size_t size) = delete;++    friend class CrossThreads;+    Type* const capture_;+  };++  class AutoThreadCrosser;++  // Connects a worker thread to the main thread via a ThreadBridge for manually+  // sharing of a single type of instrumentation.+  //+  // NOTE: This isn't visible by default. If you want to make this functionality+  // available for a specific instrumentation class, add the following with+  // public visibility within the instrumentation class:+  //+  //   using ThreadCapture<Type>::CrossThreads;+  class CrossThreads {+   public:+    explicit inline CrossThreads(const ThreadBridge& bridge)+        : previous_(GetCurrent()) {+      SetCurrent(bridge.capture_);+    }++    inline ~CrossThreads() { SetCurrent(previous_); }++   private:+    explicit inline CrossThreads(const ScopedCapture& capture)+        : previous_(GetCurrent()) {+      SetCurrent(capture.current_);+    }++    CrossThreads(const CrossThreads&) = delete;+    CrossThreads(CrossThreads&&) = delete;+    CrossThreads& operator=(const CrossThreads&) = delete;+    CrossThreads& operator=(CrossThreads&&) = delete;+    void* operator new(std::size_t size) = delete;++    friend class AutoThreadCrosser;+    Type* const previous_;+  };++  // Enables automatic crossing of threads for a specific instrumentation type+  // when ThreadCrosser::WrapCall or ThreadCrosser::WrapFunction are used. Add+  // this as a member of the implementation that you want to automatically+  // share. Use ScopedCapture *instead* if you don't want ThreadCrosser to+  // automatically share instrumentation.+  class AutoThreadCrosser : public ThreadCrosser {+   public:+    AutoThreadCrosser(Type* capture)+        : cross_with_(this), capture_to_(capture) {}++    inline Type* Previous() const { return capture_to_.Previous(); }++   private:+    AutoThreadCrosser(const AutoThreadCrosser&) = delete;+    AutoThreadCrosser(AutoThreadCrosser&&) = delete;+    AutoThreadCrosser& operator=(const AutoThreadCrosser&) = delete;+    AutoThreadCrosser& operator=(AutoThreadCrosser&&) = delete;+    void* operator new(std::size_t size) = delete;++    void FindTopAndCall(const std::function<void()>& call,+                        const ReverseScope& reverse_scope) const final;++    void ReconstructContextAndCall(+        const std::function<void()>& call,+        const ReverseScope& reverse_scope) const final;++    const ScopedCrosser cross_with_;+    const ScopedCapture capture_to_;+  };++  // Gets the most-recent object from the stack of the current thread.+  static inline Type* GetCurrent() { return current_; }++ private:+  ThreadCapture(const ThreadCapture&) = delete;+  ThreadCapture(ThreadCapture&&) = delete;+  ThreadCapture& operator=(const ThreadCapture&) = delete;+  ThreadCapture& operator=(ThreadCapture&&) = delete;+  void* operator new(std::size_t size) = delete;++  static inline void SetCurrent(Type* value) { current_ = value; }++  static thread_local Type* current_;+};++template <class Type>+thread_local Type* ThreadCapture<Type>::current_(nullptr);++template <class Type>+void ThreadCapture<Type>::AutoThreadCrosser::FindTopAndCall(+    const std::function<void()>& call,+    const ReverseScope& reverse_scope) const {+  if (cross_with_.Parent()) {+    cross_with_.Parent()->FindTopAndCall(+        call, {cross_with_.Parent(), &reverse_scope});+  } else {+    ReconstructContextAndCall(call, reverse_scope);+  }+}++template <class Type>+void ThreadCapture<Type>::AutoThreadCrosser::ReconstructContextAndCall(+    const std::function<void()>& call,+    const ReverseScope& reverse_scope) const {+  // Makes the ThreadCapture available in this scope so that it overrides the+  // default behavior of instrumentation calls made in call.+  const CrossThreads capture(capture_to_);+  if (reverse_scope.previous) {+    const auto current = reverse_scope.previous->current;+    assert(current);+    if (current) {+      current->ReconstructContextAndCall(call, *reverse_scope.previous);+    }+  } else {+    // Makes the ThreadCrosser available in this scope so that call itself can+    // cross threads again.+    const DelegateCrosser crosser(cross_with_);+    assert(call);+    if (call) {+      call();+    }+  }+}++}  // namespace capture_thread++#endif  // THREAD_CAPTURE_H_
+ base/thread-crosser.cc view
@@ -0,0 +1,33 @@+/* -----------------------------------------------------------------------------+Copyright 2017 Google Inc.++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] [kevinbarry@google.com]++#include "thread-crosser.h"++namespace capture_thread {++namespace {+thread_local ThreadCrosser* current(nullptr);+}++// static+ThreadCrosser* ThreadCrosser::GetCurrent() { return current; }++// static+void ThreadCrosser::SetCurrent(ThreadCrosser* value) { current = value; }++}  // namespace capture_thread
+ base/thread-crosser.h view
@@ -0,0 +1,254 @@+/* -----------------------------------------------------------------------------+Copyright 2017 Google Inc.++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] [kevinbarry@google.com]++#ifndef THREAD_CROSSER_H_+#define THREAD_CROSSER_H_++#include <functional>+#include <type_traits>++#include <cassert>++namespace capture_thread {++// Manages automatic thread-crossing for sharing instrumentation classes derived+// from ThreadCapture. The static API allows the caller to automatically share+// all instrumentation types that are in scope, provided they use+// AutoThreadCrosser to manage scoping. Not all classes will have this enabled,+// since it can cause unexpected results.+class ThreadCrosser {+ public:+  // Wraps a callback to share instrumentation that's currently in scope with a+  // worker thread. Call this in the main thread, then pass the returned value+  // to the worker thread.+  //+  // NOTE: The returned function will be invalidated if any instrumentation goes+  // out of scope; therefore, the main thread must wait for the worker thread to+  // call it before continuing.+  static inline std::function<void()> WrapCall(std::function<void()> call) {+    return WrapFunction(std::move(call));+  }++  // Wraps an arbitrary function to share instrumentation that's currently in+  // scope with a worker thread. Call this in the main thread, then pass the+  // returned value to the worker thread.+  //+  // NOTE: The returned function will be invalidated if any instrumentation goes+  // out of scope; therefore, the main thread must wait for the worker thread to+  // call it before continuing.+  template <class Return, class... Args>+  static inline std::function<Return(Args...)> WrapFunction(+      Return (*function)(Args...)) {+    return WrapFunction(std::function<Return(Args...)>(function));+  }++  // Wraps an arbitrary function to share instrumentation that's currently in+  // scope with a worker thread. Call this in the main thread, then pass the+  // returned value to the worker thread.+  //+  // NOTE: The returned function will be invalidated if any instrumentation goes+  // out of scope; therefore, the main thread must wait for the worker thread to+  // call it before continuing.+  template <class Return, class... Args>+  static std::function<Return(Args...)> WrapFunction(+      std::function<Return(Args...)> function);++ private:+  ThreadCrosser(const ThreadCrosser&) = delete;+  ThreadCrosser(ThreadCrosser&&) = delete;+  ThreadCrosser& operator=(const ThreadCrosser&) = delete;+  ThreadCrosser& operator=(ThreadCrosser&&) = delete;+  void* operator new(std::size_t size) = delete;++  ThreadCrosser() = default;+  virtual ~ThreadCrosser() = default;++  // Keeps track of a reverse call stack when wrapping a callback. (This is used+  // to create a linked-list of ThreadCrosser on the stack.)+  struct ReverseScope {+    const ThreadCrosser* const current;+    const ReverseScope* const previous;+  };++  // Performs the function call in the full ThreadCapture context above this+  // ThreadCrosser.+  inline void CallInFullContext(const std::function<void()>& call) const {+    FindTopAndCall(call, {this, nullptr});+  }++  // Traverses to the top of the ThreadCrosser stack to recursively rebuild the+  // stack of ThreadCapture, then calls the callback.+  virtual void FindTopAndCall(const std::function<void()>& call,+                              const ReverseScope& reverse_scope) const = 0;++  // Instantiates the ThreadCapture context associated with this ThreadCrosser,+  // then recursively calls the next ThreadCrosser.+  virtual void ReconstructContextAndCall(+      const std::function<void()>& call,+      const ReverseScope& reverse_scope) const = 0;++  class ScopedCrosser;++  // Makes a captured ThreadCrosser available within the current thread. This is+  // only to allow thread-crossing to happen again within that thread.+  class DelegateCrosser {+   public:+    explicit inline DelegateCrosser(const ScopedCrosser& crosser)+        : parent_(GetCurrent()) {+      SetCurrent(crosser.current_);+    }++    inline ~DelegateCrosser() { SetCurrent(parent_); }++   private:+    DelegateCrosser(const DelegateCrosser&) = delete;+    DelegateCrosser(DelegateCrosser&&) = delete;+    DelegateCrosser& operator=(const DelegateCrosser&) = delete;+    DelegateCrosser& operator=(DelegateCrosser&&) = delete;+    void* operator new(std::size_t size) = delete;++    ThreadCrosser* const parent_;+  };++  // Captures the ThreadCrosser so it can be used by DelegateCrosser, which will+  // make it available in another thread.+  class ScopedCrosser {+   public:+    explicit inline ScopedCrosser(ThreadCrosser* capture)+        : parent_(GetCurrent()), current_(capture) {+      SetCurrent(capture);+    }++    inline ~ScopedCrosser() { SetCurrent(Parent()); }++    inline ThreadCrosser* Parent() const { return parent_; }++   private:+    ScopedCrosser(const ScopedCrosser&) = delete;+    ScopedCrosser(ScopedCrosser&&) = delete;+    ScopedCrosser& operator=(const ScopedCrosser&) = delete;+    ScopedCrosser& operator=(ScopedCrosser&&) = delete;+    void* operator new(std::size_t size) = delete;++    friend class DelegateCrosser;+    ThreadCrosser* const parent_;+    ThreadCrosser* const current_;+  };++  // AutoMove (and its specializations) ensure that argument-passing when+  // calling a std::function doesn't make copies when it would be inappropriate,+  // e.g., when Type cannot be copied or moved. This is a class instead of a+  // function so that Type can be made explicit, which is necessary for type-+  // checking to work.++  template <class Type>+  struct AutoMove;++  // AutoCall (and its specializations) ensure that return values are not+  // inappropriately copied, e.g., when returning by reference, or when the+  // return type is void. This is a class instead of a function so that the+  // types can be made explicit, which is necessary for type-checking to work.++  template <class Return, class... Args>+  struct AutoCall;++  static ThreadCrosser* GetCurrent();+  static void SetCurrent(ThreadCrosser* value);++  template <class Type>+  friend class ThreadCapture;+};++template <class Return, class... Args>+std::function<Return(Args...)> ThreadCrosser::WrapFunction(+    std::function<Return(Args...)> function) {+  const auto current = GetCurrent();+  if (function && current) {+    return [current, function](Args... args) -> Return {+      return AutoCall<Return, Args...>::Execute(*current, function,+                                                AutoMove<Args>::Pass(args)...);+    };+  } else {+    return function;+  }+}++// Handles pass-by-value.+template <class Type>+struct ThreadCrosser::AutoMove {+  static Type&& Pass(Type& value) { return std::move(value); }+};++// Handles pass-by-reference.+template <class Type>+struct ThreadCrosser::AutoMove<Type&> {+  static Type& Pass(Type& value) { return value; }+};++// Handles return-by-value.+template <class Return, class... Args>+struct ThreadCrosser::AutoCall {+  static Return Execute(const ThreadCrosser& current,+                        const std::function<Return(Args...)>& function,+                        Args... args) {+    typename std::remove_cv<Return>::type value = Return();+    current.CallInFullContext([&value, &function, &args...] {+      value = function(AutoMove<Args>::Pass(args)...);+    });+    return value;+  }+};++// Handles return-by-reference.+template <class Return, class... Args>+struct ThreadCrosser::AutoCall<Return&, Args...> {+  static Return& Execute(const ThreadCrosser& current,+                         const std::function<Return&(Args...)>& function,+                         Args... args) {+    Return* value(nullptr);+    current.CallInFullContext([&value, &function, &args...] {+      value = &function(AutoMove<Args>::Pass(args)...);+    });+    assert(value);+    return *value;+  }+};++// Handles void return type.+template <class... Args>+struct ThreadCrosser::AutoCall<void, Args...> {+  static void Execute(const ThreadCrosser& current,+                      const std::function<void(Args...)>& function,+                      Args... args) {+    current.CallInFullContext(+        [&function, &args...] { function(AutoMove<Args>::Pass(args)...); });+  }+};++// Handles callback type.+template <>+struct ThreadCrosser::AutoCall<void> {+  static void Execute(const ThreadCrosser& current,+                      const std::function<void()>& function) {+    current.CallInFullContext(function);+  }+};++}  // namespace capture_thread++#endif  // THREAD_CROSSER_H_
bin/zeolite-setup.hs view
@@ -124,11 +124,8 @@       coSources = libraries,       coExtraFiles = [],       coExtraPaths = [],-      coExtraRequires = [],       coSourcePrefix = path,-      coExternalDefs = [],       coMode = CompileRecompile,-      coOutputName = "",       coForce = ForceAll     }   runCompiler options
− capture-thread/include/thread-capture.h
@@ -1,217 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2017 Google Inc.--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] [kevinbarry@google.com]--#ifndef THREAD_CAPTURE_H_-#define THREAD_CAPTURE_H_--#include <cassert>--#include "thread-crosser.h"--namespace capture_thread {--// Base class for instrumentation classes that need to be made available within-// a single thread, and possibly shared across threads. Derive a new class Type-// from ThreadCapture<Type> to define a new instrumentation type. Scoping is-// managed by adding a ScopedCapture *or* an AutoThreadCrosser member to-// instantiable implementations of the instrumentation. (If Type is abstract,-// add the member to the instantiable subclasses.) See ThreadCrosser for info-// about *automatic* sharing across threads, and ThreadBridge (below) for info-// about *manually* sharing across threads.-template <class Type>-class ThreadCapture {- protected:-  ThreadCapture() = default;-  virtual ~ThreadCapture() = default;--  class CrossThreads;--  // Manages scoping of instrumentation within a single thread. Use ThreadBridge-  // + CrossThreads to share instrumentation across threads. Alternatively, use-  // AutoThreadCrosser *instead* of ScopedCapture to allow ThreadCrosser to-  // handle this automatically.-  class ScopedCapture {-   public:-    explicit inline ScopedCapture(Type* capture)-        : previous_(GetCurrent()), current_(capture) {-      SetCurrent(current_);-    }--    inline ~ScopedCapture() { SetCurrent(Previous()); }--    inline Type* Previous() const { return previous_; }--   private:-    ScopedCapture(const ScopedCapture&) = delete;-    ScopedCapture(ScopedCapture&&) = delete;-    ScopedCapture& operator=(const ScopedCapture&) = delete;-    ScopedCapture& operator=(ScopedCapture&&) = delete;-    void* operator new(std::size_t size) = delete;--    friend class CrossThreads;-    Type* const previous_;-    Type* const current_;-  };--  // Creates a bridge point for sharing a single type of instrumentation between-  // threads. Create this in the main thread, then enable crossing in the worker-  // thread with CrossThreads. This is only needed if the instrumentation uses-  // ScopedCapture instead of AutoThreadCrosser.-  //-  // NOTE: This isn't visible by default. If you want to make this functionality-  // available for a specific instrumentation class, add the following with-  // public visibility within the instrumentation class:-  //-  //   using ThreadCapture<Type>::ThreadBridge;-  class ThreadBridge {-   public:-    inline ThreadBridge() : capture_(GetCurrent()) {}--   private:-    ThreadBridge(const ThreadBridge&) = delete;-    ThreadBridge(ThreadBridge&&) = delete;-    ThreadBridge& operator=(const ThreadBridge&) = delete;-    ThreadBridge& operator=(ThreadBridge&&) = delete;-    void* operator new(std::size_t size) = delete;--    friend class CrossThreads;-    Type* const capture_;-  };--  class AutoThreadCrosser;--  // Connects a worker thread to the main thread via a ThreadBridge for manually-  // sharing of a single type of instrumentation.-  //-  // NOTE: This isn't visible by default. If you want to make this functionality-  // available for a specific instrumentation class, add the following with-  // public visibility within the instrumentation class:-  //-  //   using ThreadCapture<Type>::CrossThreads;-  class CrossThreads {-   public:-    explicit inline CrossThreads(const ThreadBridge& bridge)-        : previous_(GetCurrent()) {-      SetCurrent(bridge.capture_);-    }--    inline ~CrossThreads() { SetCurrent(previous_); }--   private:-    explicit inline CrossThreads(const ScopedCapture& capture)-        : previous_(GetCurrent()) {-      SetCurrent(capture.current_);-    }--    CrossThreads(const CrossThreads&) = delete;-    CrossThreads(CrossThreads&&) = delete;-    CrossThreads& operator=(const CrossThreads&) = delete;-    CrossThreads& operator=(CrossThreads&&) = delete;-    void* operator new(std::size_t size) = delete;--    friend class AutoThreadCrosser;-    Type* const previous_;-  };--  // Enables automatic crossing of threads for a specific instrumentation type-  // when ThreadCrosser::WrapCall or ThreadCrosser::WrapFunction are used. Add-  // this as a member of the implementation that you want to automatically-  // share. Use ScopedCapture *instead* if you don't want ThreadCrosser to-  // automatically share instrumentation.-  class AutoThreadCrosser : public ThreadCrosser {-   public:-    AutoThreadCrosser(Type* capture)-        : cross_with_(this), capture_to_(capture) {}--    inline Type* Previous() const { return capture_to_.Previous(); }--   private:-    AutoThreadCrosser(const AutoThreadCrosser&) = delete;-    AutoThreadCrosser(AutoThreadCrosser&&) = delete;-    AutoThreadCrosser& operator=(const AutoThreadCrosser&) = delete;-    AutoThreadCrosser& operator=(AutoThreadCrosser&&) = delete;-    void* operator new(std::size_t size) = delete;--    void FindTopAndCall(const std::function<void()>& call,-                        const ReverseScope& reverse_scope) const final;--    void ReconstructContextAndCall(-        const std::function<void()>& call,-        const ReverseScope& reverse_scope) const final;--    const ScopedCrosser cross_with_;-    const ScopedCapture capture_to_;-  };--  // Gets the most-recent object from the stack of the current thread.-  static inline Type* GetCurrent() { return current_; }-- private:-  ThreadCapture(const ThreadCapture&) = delete;-  ThreadCapture(ThreadCapture&&) = delete;-  ThreadCapture& operator=(const ThreadCapture&) = delete;-  ThreadCapture& operator=(ThreadCapture&&) = delete;-  void* operator new(std::size_t size) = delete;--  static inline void SetCurrent(Type* value) { current_ = value; }--  static thread_local Type* current_;-};--template <class Type>-thread_local Type* ThreadCapture<Type>::current_(nullptr);--template <class Type>-void ThreadCapture<Type>::AutoThreadCrosser::FindTopAndCall(-    const std::function<void()>& call,-    const ReverseScope& reverse_scope) const {-  if (cross_with_.Parent()) {-    cross_with_.Parent()->FindTopAndCall(-        call, {cross_with_.Parent(), &reverse_scope});-  } else {-    ReconstructContextAndCall(call, reverse_scope);-  }-}--template <class Type>-void ThreadCapture<Type>::AutoThreadCrosser::ReconstructContextAndCall(-    const std::function<void()>& call,-    const ReverseScope& reverse_scope) const {-  // Makes the ThreadCapture available in this scope so that it overrides the-  // default behavior of instrumentation calls made in call.-  const CrossThreads capture(capture_to_);-  if (reverse_scope.previous) {-    const auto current = reverse_scope.previous->current;-    assert(current);-    if (current) {-      current->ReconstructContextAndCall(call, *reverse_scope.previous);-    }-  } else {-    // Makes the ThreadCrosser available in this scope so that call itself can-    // cross threads again.-    const DelegateCrosser crosser(cross_with_);-    assert(call);-    if (call) {-      call();-    }-  }-}--}  // namespace capture_thread--#endif  // THREAD_CAPTURE_H_
− capture-thread/include/thread-crosser.h
@@ -1,254 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2017 Google Inc.--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] [kevinbarry@google.com]--#ifndef THREAD_CROSSER_H_-#define THREAD_CROSSER_H_--#include <functional>-#include <type_traits>--#include <cassert>--namespace capture_thread {--// Manages automatic thread-crossing for sharing instrumentation classes derived-// from ThreadCapture. The static API allows the caller to automatically share-// all instrumentation types that are in scope, provided they use-// AutoThreadCrosser to manage scoping. Not all classes will have this enabled,-// since it can cause unexpected results.-class ThreadCrosser {- public:-  // Wraps a callback to share instrumentation that's currently in scope with a-  // worker thread. Call this in the main thread, then pass the returned value-  // to the worker thread.-  //-  // NOTE: The returned function will be invalidated if any instrumentation goes-  // out of scope; therefore, the main thread must wait for the worker thread to-  // call it before continuing.-  static inline std::function<void()> WrapCall(std::function<void()> call) {-    return WrapFunction(std::move(call));-  }--  // Wraps an arbitrary function to share instrumentation that's currently in-  // scope with a worker thread. Call this in the main thread, then pass the-  // returned value to the worker thread.-  //-  // NOTE: The returned function will be invalidated if any instrumentation goes-  // out of scope; therefore, the main thread must wait for the worker thread to-  // call it before continuing.-  template <class Return, class... Args>-  static inline std::function<Return(Args...)> WrapFunction(-      Return (*function)(Args...)) {-    return WrapFunction(std::function<Return(Args...)>(function));-  }--  // Wraps an arbitrary function to share instrumentation that's currently in-  // scope with a worker thread. Call this in the main thread, then pass the-  // returned value to the worker thread.-  //-  // NOTE: The returned function will be invalidated if any instrumentation goes-  // out of scope; therefore, the main thread must wait for the worker thread to-  // call it before continuing.-  template <class Return, class... Args>-  static std::function<Return(Args...)> WrapFunction(-      std::function<Return(Args...)> function);-- private:-  ThreadCrosser(const ThreadCrosser&) = delete;-  ThreadCrosser(ThreadCrosser&&) = delete;-  ThreadCrosser& operator=(const ThreadCrosser&) = delete;-  ThreadCrosser& operator=(ThreadCrosser&&) = delete;-  void* operator new(std::size_t size) = delete;--  ThreadCrosser() = default;-  virtual ~ThreadCrosser() = default;--  // Keeps track of a reverse call stack when wrapping a callback. (This is used-  // to create a linked-list of ThreadCrosser on the stack.)-  struct ReverseScope {-    const ThreadCrosser* const current;-    const ReverseScope* const previous;-  };--  // Performs the function call in the full ThreadCapture context above this-  // ThreadCrosser.-  inline void CallInFullContext(const std::function<void()>& call) const {-    FindTopAndCall(call, {this, nullptr});-  }--  // Traverses to the top of the ThreadCrosser stack to recursively rebuild the-  // stack of ThreadCapture, then calls the callback.-  virtual void FindTopAndCall(const std::function<void()>& call,-                              const ReverseScope& reverse_scope) const = 0;--  // Instantiates the ThreadCapture context associated with this ThreadCrosser,-  // then recursively calls the next ThreadCrosser.-  virtual void ReconstructContextAndCall(-      const std::function<void()>& call,-      const ReverseScope& reverse_scope) const = 0;--  class ScopedCrosser;--  // Makes a captured ThreadCrosser available within the current thread. This is-  // only to allow thread-crossing to happen again within that thread.-  class DelegateCrosser {-   public:-    explicit inline DelegateCrosser(const ScopedCrosser& crosser)-        : parent_(GetCurrent()) {-      SetCurrent(crosser.current_);-    }--    inline ~DelegateCrosser() { SetCurrent(parent_); }--   private:-    DelegateCrosser(const DelegateCrosser&) = delete;-    DelegateCrosser(DelegateCrosser&&) = delete;-    DelegateCrosser& operator=(const DelegateCrosser&) = delete;-    DelegateCrosser& operator=(DelegateCrosser&&) = delete;-    void* operator new(std::size_t size) = delete;--    ThreadCrosser* const parent_;-  };--  // Captures the ThreadCrosser so it can be used by DelegateCrosser, which will-  // make it available in another thread.-  class ScopedCrosser {-   public:-    explicit inline ScopedCrosser(ThreadCrosser* capture)-        : parent_(GetCurrent()), current_(capture) {-      SetCurrent(capture);-    }--    inline ~ScopedCrosser() { SetCurrent(Parent()); }--    inline ThreadCrosser* Parent() const { return parent_; }--   private:-    ScopedCrosser(const ScopedCrosser&) = delete;-    ScopedCrosser(ScopedCrosser&&) = delete;-    ScopedCrosser& operator=(const ScopedCrosser&) = delete;-    ScopedCrosser& operator=(ScopedCrosser&&) = delete;-    void* operator new(std::size_t size) = delete;--    friend class DelegateCrosser;-    ThreadCrosser* const parent_;-    ThreadCrosser* const current_;-  };--  // AutoMove (and its specializations) ensure that argument-passing when-  // calling a std::function doesn't make copies when it would be inappropriate,-  // e.g., when Type cannot be copied or moved. This is a class instead of a-  // function so that Type can be made explicit, which is necessary for type--  // checking to work.--  template <class Type>-  struct AutoMove;--  // AutoCall (and its specializations) ensure that return values are not-  // inappropriately copied, e.g., when returning by reference, or when the-  // return type is void. This is a class instead of a function so that the-  // types can be made explicit, which is necessary for type-checking to work.--  template <class Return, class... Args>-  struct AutoCall;--  static ThreadCrosser* GetCurrent();-  static void SetCurrent(ThreadCrosser* value);--  template <class Type>-  friend class ThreadCapture;-};--template <class Return, class... Args>-std::function<Return(Args...)> ThreadCrosser::WrapFunction(-    std::function<Return(Args...)> function) {-  const auto current = GetCurrent();-  if (function && current) {-    return [current, function](Args... args) -> Return {-      return AutoCall<Return, Args...>::Execute(*current, function,-                                                AutoMove<Args>::Pass(args)...);-    };-  } else {-    return function;-  }-}--// Handles pass-by-value.-template <class Type>-struct ThreadCrosser::AutoMove {-  static Type&& Pass(Type& value) { return std::move(value); }-};--// Handles pass-by-reference.-template <class Type>-struct ThreadCrosser::AutoMove<Type&> {-  static Type& Pass(Type& value) { return value; }-};--// Handles return-by-value.-template <class Return, class... Args>-struct ThreadCrosser::AutoCall {-  static Return Execute(const ThreadCrosser& current,-                        const std::function<Return(Args...)>& function,-                        Args... args) {-    typename std::remove_cv<Return>::type value = Return();-    current.CallInFullContext([&value, &function, &args...] {-      value = function(AutoMove<Args>::Pass(args)...);-    });-    return value;-  }-};--// Handles return-by-reference.-template <class Return, class... Args>-struct ThreadCrosser::AutoCall<Return&, Args...> {-  static Return& Execute(const ThreadCrosser& current,-                         const std::function<Return&(Args...)>& function,-                         Args... args) {-    Return* value(nullptr);-    current.CallInFullContext([&value, &function, &args...] {-      value = &function(AutoMove<Args>::Pass(args)...);-    });-    assert(value);-    return *value;-  }-};--// Handles void return type.-template <class... Args>-struct ThreadCrosser::AutoCall<void, Args...> {-  static void Execute(const ThreadCrosser& current,-                      const std::function<void(Args...)>& function,-                      Args... args) {-    current.CallInFullContext(-        [&function, &args...] { function(AutoMove<Args>::Pass(args)...); });-  }-};--// Handles callback type.-template <>-struct ThreadCrosser::AutoCall<void> {-  static void Execute(const ThreadCrosser& current,-                      const std::function<void()>& function) {-    current.CallInFullContext(function);-  }-};--}  // namespace capture_thread--#endif  // THREAD_CROSSER_H_
− capture-thread/src/thread-crosser.cc
@@ -1,33 +0,0 @@-/* ------------------------------------------------------------------------------Copyright 2017 Google Inc.--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] [kevinbarry@google.com]--#include "thread-crosser.h"--namespace capture_thread {--namespace {-thread_local ThreadCrosser* current(nullptr);-}--// static-ThreadCrosser* ThreadCrosser::GetCurrent() { return current; }--// static-void ThreadCrosser::SetCurrent(ThreadCrosser* value) { current = value; }--}  // namespace capture_thread
lib/file/.zeolite-module view
@@ -4,11 +4,13 @@   "../util" ] extra_files: [-  "file/Category_RawFileReader.cpp"-  "file/Category_RawFileWriter.cpp"-]-external: [-  RawFileReader-  RawFileWriter+  category_source {+    source: "file/Category_RawFileReader.cpp"+    categories: [RawFileReader]+  }+  category_source {+    source: "file/Category_RawFileWriter.cpp"+    categories: [RawFileWriter]+  } ]-mode: incremental+mode: incremental {}
lib/util/.zeolite-module view
@@ -1,13 +1,17 @@ root: ".." path: "util" extra_files: [-  "util/Category_Argv.cpp"-  "util/Category_SimpleInput.cpp"-  "util/Category_SimpleOutput.cpp"-]-external: [-  Argv-  SimpleInput-  SimpleOutput+  category_source {+    source: "util/Category_Argv.cpp"+    categories: [Argv]+  }+  category_source {+    source: "util/Category_SimpleInput.cpp"+    categories: [SimpleInput]+  }+  category_source {+    source: "util/Category_SimpleOutput.cpp"+    categories: [SimpleOutput]+  } ]-mode: incremental+mode: incremental {}
src/Cli/CompileMetadata.hs view
@@ -39,7 +39,6 @@     cmNamespace :: String, -- TODO: Use Namespace here?     cmPublicDeps :: [String],     cmPrivateDeps :: [String],-    cmExtraRequires :: [CategoryIdentifier],     cmCategories :: [String],     cmSubdirs :: [String],     cmPublicFiles :: [String],@@ -47,6 +46,7 @@     cmTestFiles :: [String],     cmHxxFiles :: [String],     cmCxxFiles :: [String],+    cmLinkFlags :: [String],     cmObjectFiles :: [ObjectFile]   }   deriving (Eq,Show)@@ -88,11 +88,8 @@     rmPath :: String,     rmPublicDeps :: [String],     rmPrivateDeps :: [String],-    rmExtraFiles :: [String],+    rmExtraFiles :: [ExtraSource],     rmExtraPaths :: [String],-    rmExtraRequires :: [String],-    rmExternalDefs :: [String],-    rmMode :: CompileMode,-    rmOutputName :: String+    rmMode :: CompileMode   }   deriving (Eq,Show)
src/Cli/CompileOptions.hs view
@@ -21,9 +21,14 @@ module Cli.CompileOptions (   CompileOptions(..),   CompileMode(..),+  ExtraSource(..),   ForceMode(..),   HelpMode(..),   emptyCompileOptions,+  getLinkFlags,+  getSourceCategories,+  getSourceDeps,+  getSourceFile,   isCompileBinary,   isCompileIncremental,   isCompileRecompile,@@ -39,13 +44,10 @@     coPublicDeps :: [String],     coPrivateDeps :: [String],     coSources :: [String],-    coExtraFiles :: [String],+    coExtraFiles :: [ExtraSource],     coExtraPaths :: [String],-    coExtraRequires :: [String],     coSourcePrefix :: String,-    coExternalDefs :: [String],     coMode :: CompileMode,-    coOutputName :: String,     coForce :: ForceMode   } deriving (Show) @@ -58,14 +60,34 @@     coSources = [],     coExtraFiles = [],     coExtraPaths = [],-    coExtraRequires = [],     coSourcePrefix = "",-    coExternalDefs = [],     coMode = CompileUnspecified,-    coOutputName = "",     coForce = DoNotForce   } +data ExtraSource =+  CategorySource {+    csSource :: String,+    csCategories :: [String],+    csDepCategories :: [String]+  } |+  OtherSource {+    osSource :: String+  }+  deriving (Eq,Show)++getSourceFile :: ExtraSource -> String+getSourceFile (CategorySource s _ _) = s+getSourceFile (OtherSource s)        = s++getSourceCategories :: ExtraSource -> [String]+getSourceCategories (CategorySource _ cs _) = cs+getSourceCategories (OtherSource _)         = []++getSourceDeps :: ExtraSource -> [String]+getSourceDeps (CategorySource _ _ ds) = ds+getSourceDeps (OtherSource _)         = []+ data HelpMode = HelpNeeded | HelpNotNeeded | HelpUnspecified deriving (Eq,Show)  data ForceMode = DoNotForce | AllowRecompile | ForceRecompile | ForceAll deriving (Eq,Ord,Show)@@ -73,24 +95,28 @@ data CompileMode =   CompileBinary {     cbCategory :: String,-    cbFunction :: String+    cbFunction :: String,+    cbOutputName :: String,+    cbLinkFlags :: [String]   } |   ExecuteTests {     etInclude :: [String]   } |-  CompileIncremental |+  CompileIncremental {+    ciLinkFlags :: [String]+  } |   CompileRecompile |   CreateTemplates |   CompileUnspecified   deriving (Eq,Show)  isCompileBinary :: CompileMode -> Bool-isCompileBinary (CompileBinary _ _) = True-isCompileBinary _                   = False+isCompileBinary (CompileBinary _ _ _ _) = True+isCompileBinary _                       = False  isCompileIncremental :: CompileMode -> Bool-isCompileIncremental CompileIncremental = True-isCompileIncremental _                  = False+isCompileIncremental (CompileIncremental _) = True+isCompileIncremental _                      = False  isCompileRecompile :: CompileMode -> Bool isCompileRecompile CompileRecompile = True@@ -107,3 +133,8 @@ maybeDisableHelp :: HelpMode -> HelpMode maybeDisableHelp HelpUnspecified = HelpNotNeeded maybeDisableHelp h               = h++getLinkFlags :: CompileMode -> [String]+getLinkFlags (CompileBinary _ _ _ lf) = lf+getLinkFlags (CompileIncremental lf)  = lf+getLinkFlags _                        = []
src/Cli/Compiler.hs view
@@ -21,6 +21,7 @@ ) where  import Control.Monad (when)+import Data.Either (partitionEithers) import Data.List (intercalate,isSuffixOf,nub,sort) import System.Directory import System.Exit@@ -49,9 +50,10 @@   runCompiler :: CompileOptions -> IO ()-runCompiler (CompileOptions _ _ _ ds _ _ _ p _ (ExecuteTests tp) _ f) = do+runCompiler (CompileOptions _ _ _ ds _ _ p (ExecuteTests tp) f) = do   (backend,resolver) <- loadConfig-  ds' <- sequence $ map (preloadModule backend resolver) ds+  base <- resolveBaseModule resolver+  ds' <- sequence $ map (preloadModule backend base) ds   let possibleTests = Set.fromList $ concat $ map getTestsFromPreload ds'   case Set.toList $ allowTests `Set.difference` possibleTests of        [] -> return ()@@ -59,13 +61,12 @@          hPutStr stderr $ "Some test files do not occur in the selected modules: " ++                           intercalate ", " (map show ts) ++ "\n"          exitFailure-  allResults <- fmap concat $ sequence $ map (runTests backend) ds'+  allResults <- fmap concat $ sequence $ map (runTests backend base) ds'   let passed = sum $ map (fst . fst) allResults   let failed = sum $ map (snd . fst) allResults   processResults passed failed (mergeAllM $ map snd allResults) where-    preloadModule b r d = do+    preloadModule b base d = do       m <- loadMetadata (p </> d)-      base <- resolveBaseModule r       (fr1,deps1) <- loadPublicDeps (getCompilerHash b) [base,p </> d]       checkAllowedStale fr1 f       (fr2,deps2) <- loadPrivateDeps (getCompilerHash b) deps1@@ -74,11 +75,11 @@     getTestsFromPreload (_,m,_,_) = cmTestFiles m     allowTests = Set.fromList tp     isTestAllowed t = if null allowTests then True else t `Set.member` allowTests-    runTests :: CompilerBackend b => b ->+    runTests :: CompilerBackend b => b -> String ->                 (String,CompileMetadata,[CompileMetadata],[CompileMetadata]) ->                 IO [((Int,Int),CompileInfo ())]-    runTests b (d,m,deps1,deps2) = do-      let paths = getIncludePathsForDeps deps1+    runTests b base (d,m,deps1,deps2) = do+      let paths = base:(getIncludePathsForDeps deps1)       let ss = fixPaths $ getSourceFilesForDeps deps1       let os = getObjectFilesForDeps deps2       ss' <- zipWithContents p ss@@ -98,7 +99,7 @@       | otherwise = do           hPutStrLn stderr $ "\nPassed: " ++ show passed ++ " test(s), Failed: " ++ show failed ++ " test(s)"           hPutStrLn stderr $ "Zeolite tests passed."-runCompiler (CompileOptions h _ _ ds _ _ _ p _ CompileRecompile _ f) = do+runCompiler (CompileOptions h _ _ ds _ _ p CompileRecompile f) = do   (backend,_) <- loadConfig   fmap mergeAll $ sequence $ map (recompileSingle $ getCompilerHash backend) ds where     recompileSingle h2 d0 = do@@ -112,7 +113,7 @@         maybeCompile (Just rm') upToDate           | f < ForceAll && upToDate = hPutStrLn stderr $ "Path " ++ d0 ++ " is up to date."           | otherwise = do-              let (ModuleConfig p2 d is is2 es ep ec ex m o) = rm'+              let (ModuleConfig p2 d is is2 es ep m) = rm'               -- In case the module is manually configured with a p such as "..",               -- since the absolute path might not be known ahead of time.               absolute <- canonicalizePath (p </> d0)@@ -124,15 +125,12 @@                   coSources = [d],                   coExtraFiles = es,                   coExtraPaths = ep,-                  coExtraRequires = ec,                   coSourcePrefix = fixed,-                  coExternalDefs = ex,                   coMode = m,-                  coOutputName = o,                   coForce = if f == ForceAll then ForceRecompile else AllowRecompile                 }               runCompiler recompile-runCompiler (CompileOptions _ is is2 ds es ep ec p ex m o f) = do+runCompiler (CompileOptions _ is is2 ds es ep p m f) = do   (backend,resolver) <- loadConfig   as  <- fmap fixPaths $ sequence $ map (resolveModule resolver p) is   as2 <- fmap fixPaths $ sequence $ map (resolveModule resolver p) is2@@ -147,7 +145,6 @@         createBinary backend resolver (deps ++ deps2) m ms   hPutStrLn stderr $ "Zeolite compilation succeeded." where     ep' = fixPaths $ map (p </>) ep-    es' = fixPaths $ map (p </>) es     processPath b r deps as as2 d = do       isConfigured <- isPathConfigured d       when (isConfigured && f == DoNotForce) $ do@@ -161,12 +158,9 @@         rmPath = d,         rmPublicDeps = as,         rmPrivateDeps = as2,-        rmExtraFiles = sort es,-        rmExtraPaths = sort ep,-        rmExtraRequires = sort ec,-        rmExternalDefs = ex,-        rmMode = m,-        rmOutputName = o+        rmExtraFiles = es,+        rmExtraPaths = ep,+        rmMode = m       }       when (f == DoNotForce || f == ForceAll) $ writeRecompile (p </> d) rm       (ps,xs,ts) <- findSourceFiles p d@@ -182,17 +176,17 @@                     return $ bpDeps ++ deps       let ss = fixPaths $ getSourceFilesForDeps deps2       ss' <- zipWithContents p ss-      let paths = getIncludePathsForDeps deps2+      let paths = base:(getIncludePathsForDeps deps2)       ps' <- zipWithContents p ps       xs' <- zipWithContents p xs       ns0 <- canonicalizePath (p </> d) >>= return . StaticNamespace . publicNamespace       let ns2 = map StaticNamespace $ filter (not . null) $ getNamespacesForDeps deps       let fs = compileAll ns0 ns2 ss' ps' xs'-      writeOutput b r paths ns0 deps2 d as as2+      writeOutput b paths ns0 deps2 d as as2                   (map takeFileName ps)                   (map takeFileName xs)                   (map takeFileName ts) fs-    writeOutput b r paths ns0 deps d as as2 ps xs ts fs+    writeOutput b paths ns0 deps d as as2 ps xs ts fs       | isCompileError fs = do           formatWarnings fs           hPutStr stderr $ "Compiler errors:\n" ++ (show $ getCompileError fs)@@ -207,48 +201,29 @@           let hxx   = filter (isSuffixOf ".hpp" . coFilename)       fs'           let other = filter (not . isSuffixOf ".hpp" . coFilename) fs'           os1 <- sequence $ map (writeOutputFile b (show ns0) paths' d) $ hxx ++ other-          actual <- resolveModule r p d-          isBase <- isBaseModule r actual-          -- Base files should be compiled to .o and not .a.-          let extraComp = if isBase-                             then compileBuiltinFile-                             else compileExtraFile-          os2 <- fmap concat $ sequence $ map (extraComp b (show ns0) paths' d) es'-          let (hxx',cxx,os') = sortCompiledFiles $ map (\f2 -> show (coNamespace f2) </> coFilename f2) fs' ++ es'+          let files = map (\f2 -> getCachedPath (p </> d) (show $ coNamespace f2) (coFilename f2)) fs' +++                      map (\f2 -> p </> getSourceFile f2) es+          files' <- sequence $ map checkOwnedFile files+          os2 <- fmap concat $ sequence $ map (compileExtraSource b (show ns0) paths' d) es+          let (hxx',cxx,os') = sortCompiledFiles files'+          let (osCat,osOther) = partitionEithers os2           path <- canonicalizePath $ p </> d-          let os1' = resolveObjectDeps path os1 deps-          let cm0 = CompileMetadata {+          let os1' = resolveObjectDeps path (os1 ++ osCat) deps+          let cm = CompileMetadata {               cmVersionHash = getCompilerHash b,               cmPath = path,               cmNamespace = show ns0,               cmPublicDeps = as,               cmPrivateDeps = as2,-              cmExtraRequires = [],               cmCategories = sort $ map show pc,-              cmSubdirs = sort $ ss' ++ ep',+              cmSubdirs = sort $ ss',               cmPublicFiles = sort ps,               cmPrivateFiles = sort xs,               cmTestFiles = sort ts,               cmHxxFiles = sort hxx',               cmCxxFiles = sort cxx,-              cmObjectFiles = os1' ++ os2 ++ map OtherObjectFile os'-            }-          let ec' = resolveCategoryDeps ec (cm0:deps)-          let cm = CompileMetadata {-              cmVersionHash = cmVersionHash cm0,-              cmPath = cmPath cm0,-              cmNamespace = cmNamespace cm0,-              cmPublicDeps = cmPublicDeps cm0,-              cmPrivateDeps = cmPrivateDeps cm0,-              cmExtraRequires = ec',-              cmCategories = cmCategories cm0,-              cmSubdirs = cmSubdirs cm0,-              cmPublicFiles = cmPublicFiles cm0,-              cmPrivateFiles = cmPrivateFiles cm0,-              cmTestFiles = cmTestFiles cm0,-              cmHxxFiles = cmHxxFiles cm0,-              cmCxxFiles = cmCxxFiles cm0,-              cmObjectFiles = cmObjectFiles cm0+              cmLinkFlags = getLinkFlags m,+              cmObjectFiles = os1' ++ osOther ++ map OtherObjectFile os'             }           when (not $ isCreateTemplates m) $ writeMetadata (p </> d) cm           return (cm,mf)@@ -269,16 +244,41 @@            o2 <- runCxxCommand b command            return $ ([o2],ca)          else return ([],ca)-    compileExtraFile = compileExtraCommon True-    compileBuiltinFile = compileExtraCommon False-    compileExtraCommon e b ns0 paths d f2+    compileExtraSource b ns0 paths d (CategorySource f2 cs ds2) = do+      f2' <- compileExtraFile False b ns0 paths d f2+      let ds2' = nub $ cs ++ ds2+      case f2' of+           Nothing -> return []+           Just o  -> return $ map (\c -> Left $ ([o],fakeCxxForSource ns0 ds2' c)) cs+    compileExtraSource b ns0 paths d (OtherSource f2) = do+      f2' <- compileExtraFile True b ns0 paths d f2+      case f2' of+           Just o  -> return [Right $ OtherObjectFile o]+           Nothing -> return []+    fakeCxxForSource ns ds2 c = CxxOutput {+        coCategory = Just (CategoryName c),+        coFilename = "",+        coNamespace = ns',+        coUsesNamespace = [ns'],+        coUsesCategory = map CategoryName ds2,+        coOutput = []+      } where+        ns' = if null ns then NoNamespace else StaticNamespace ns+    checkOwnedFile f2 = do+      exists <- doesFileExist f2+      when (not exists) $ do+        hPutStrLn stderr $ "Owned file \"" ++ f2 ++ "\" does not exist."+        hPutStrLn stderr $ "Zeolite compilation failed."+        exitFailure+      canonicalizePath f2+    compileExtraFile e b ns0 paths d f2       | isSuffixOf ".cpp" f2 || isSuffixOf ".cc" f2 = do-          let f2' = p </> d </> f2+          let f2' = p </> f2           createCachePath (p </> d)           let command = CompileToObject f2' (getCachedPath (p </> d) "" "") dynamicNamespaceName ns0 paths e-          o2 <- runCxxCommand b command-          return [OtherObjectFile o2]-      | otherwise = return []+          fmap Just $ runCxxCommand b command+      | isSuffixOf ".a" f2 || isSuffixOf ".o" f2 = return (Just f2)+      | otherwise = return Nothing     processTemplates deps d = do       (ps,xs,_) <- findSourceFiles p d       ps' <- zipWithContents p ps@@ -325,7 +325,7 @@           cnNamespaces = ns0:ns2,           cnPublic = cs'',           cnPrivate = xa,-          cnExternal = ex+          cnExternal = concat $ map getSourceCategories es         }       xx <- compileCategoryModule cm       let pc = map getCategoryName cs''@@ -339,11 +339,7 @@     addIncludes tm fs = do       cs <- fmap concat $ collectAllOrErrorM $ map parsePublicSource fs       includeNewTypes tm cs-    getBinaryName (CompileBinary n _)-      | null o    = canonicalizePath $ p </> head ds </> n-      | otherwise = canonicalizePath $ p </> head ds </> o-    getBinaryName _ = return ""-    createBinary b r deps ma@(CompileBinary n _) ms+    createBinary b r deps (CompileBinary n _ o lf) ms       | length ms > 1 = do         hPutStrLn stderr $ "Multiple matches for main category " ++ n ++ "."         exitFailure@@ -351,7 +347,9 @@         hPutStrLn stderr $ "Main category " ++ n ++ " not found."         exitFailure       | otherwise = do-          f0 <- getBinaryName ma+          f0 <- if null o+                   then canonicalizePath $ p </> head ds </> n+                   else canonicalizePath $ p </> head ds </> o           let (CxxOutput _ _ _ ns2 req content) = head ms           -- TODO: Create a helper or a constant or something.           (o',h) <- mkstemps "/tmp/zmain_" ".cpp"@@ -360,17 +358,17 @@           base <- resolveBaseModule r           (_,bpDeps) <- loadPublicDeps (getCompilerHash b) [base]           (_,deps2) <- loadPrivateDeps (getCompilerHash b) (bpDeps ++ deps)-          let paths = fixPaths $ getIncludePathsForDeps deps2+          let lf' = lf ++ getLinkFlagsForDeps deps2+          let paths = fixPaths $ base:(getIncludePathsForDeps deps2)           let os    = getObjectFilesForDeps deps2-          let req2 = getRequiresFromDeps deps2-          let ofr = getObjectFileResolver req2 os+          let ofr = getObjectFileResolver os           let os' = ofr ns2 req-          let command = CompileToBinary o' os' f0 paths+          let command = CompileToBinary o' os' f0 paths lf'           hPutStrLn stderr $ "Creating binary " ++ f0           _ <- runCxxCommand b command           removeFile o'     createBinary _ _ _ _ _ = return ()-    maybeCreateMain cm (CompileBinary n f2) =+    maybeCreateMain cm (CompileBinary n f2 _ _) =       fmap (:[]) $ compileModuleMain cm (CategoryName n) (FunctionName f2)     maybeCreateMain _ _ = return [] 
src/Cli/ParseCompileOptions.hs view
@@ -24,16 +24,14 @@ ) where  import Control.Monad (when)-import Data.List (intercalate,isSuffixOf)+import Data.List (isSuffixOf) import System.Directory import System.Exit-import System.FilePath (takeExtension) import System.IO import Text.Regex.TDFA -- Not safe!  import Base.CompileError import Cli.CompileOptions-import Cli.ProcessMetadata (allowedExtraTypes) import Config.LoadConfig (compilerVersion,rootPath)  @@ -58,7 +56,6 @@     "  --version: Show the compiler version and immediately exit.",     "",     "Options:",-    "  -e [path|file]: Include an extra source file or path during compilation.",     "  -f: Force compilation instead of recompiling with -r.",     "  -i [path]: A single source path to include as a *public* dependency.",     "  -I [path]: A single source path to include as a *private* dependency.",@@ -103,101 +100,88 @@     | otherwise = argError n f $ "Invalid file path for " ++ o ++ "."   checkCategoryName n c o     | c =~ "^[A-Z][A-Za-z0-9]+$" = return ()-    | null o    = argError n c "Invalid category name."     | otherwise = argError n c $ "Invalid category name for " ++ o ++ "."   checkFunctionName n d o     | d =~ "^[a-z][A-Za-z0-9]+$" = return ()-    | null d    = argError n d "Invalid function name."     | otherwise = argError n d $ "Invalid function name for " ++ o ++ "."    parseSingle _ [] = undefined -  parseSingle (CompileOptions _ is is2 ds es ep ec p ex m o f) ((_,"-h"):os) =-    return (os,CompileOptions HelpNeeded is is2 ds es ep ec p ex m o f)+  parseSingle (CompileOptions _ is is2 ds es ep p m f) ((_,"-h"):os) =+    return (os,CompileOptions HelpNeeded is is2 ds es ep p m f) -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o _) ((_,"-f"):os) =-    return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep ec p ex m o ForceAll)+  parseSingle (CompileOptions h is is2 ds es ep p m _) ((_,"-f"):os) =+    return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep p m ForceAll) -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"-c"):os)+  parseSingle (CompileOptions h is is2 ds es ep p m f) ((n,"-c"):os)     | m /= CompileUnspecified = argError n "-c" "Compiler mode already set."-    | otherwise = return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep ec p ex CompileIncremental o f)+    | otherwise = return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep p (CompileIncremental []) f) -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"-r"):os)+  parseSingle (CompileOptions h is is2 ds es ep p m f) ((n,"-r"):os)     | m /= CompileUnspecified = argError n "-r" "Compiler mode already set."-    | otherwise = return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep ec p ex CompileRecompile o f)+    | otherwise = return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep p CompileRecompile f) -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"-t"):os)+  parseSingle (CompileOptions h is is2 ds es ep p m f) ((n,"-t"):os)     | m /= CompileUnspecified = argError n "-t" "Compiler mode already set."-    | otherwise = return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep ec p ex (ExecuteTests []) o f)+    | otherwise = return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep p (ExecuteTests []) f) -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"--templates"):os)+  parseSingle (CompileOptions h is is2 ds es ep p m f) ((n,"--templates"):os)     | m /= CompileUnspecified = argError n "-t" "Compiler mode already set."-    | otherwise = return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep ec p ex CreateTemplates o f)+    | otherwise = return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep p CreateTemplates f) -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"-m"):os)+  parseSingle (CompileOptions h is is2 ds es ep p m f) ((n,"-m"):os)     | m /= CompileUnspecified = argError n "-m" "Compiler mode already set."     | otherwise = update os where       update ((n2,c):os2) =  do         (t,fn) <- check $ break (== '.') c         checkCategoryName n2 t  "-m"         checkFunctionName n2 fn "-m"-        return (os2,CompileOptions (maybeDisableHelp h) is is2 ds es ep ec p ex (CompileBinary t fn) o f) where+        return (os2,CompileOptions (maybeDisableHelp h) is is2 ds es ep p (CompileBinary t fn "" []) f) where           check (t,"")     = return (t,defaultMainFunc)           check (t,'.':fn) = return (t,fn)           check _          = argError n2 "-m" $ "Invalid entry point \"" ++ c ++ "\"."       update _ = argError n "-m" "Requires a category name." -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"-o"):os)+  parseSingle (CompileOptions h is is2 ds es ep p (CompileBinary t fn o lf) f) ((n,"-o"):os)     | not $ null o = argError n "-o" "Output name already set."     | otherwise = update os where       update ((n2,o2):os2) = do         checkPathName n2 o2 "-o"-        return (os2,CompileOptions (maybeDisableHelp h) is is2 ds es ep ec p ex m o2 f)+        return (os2,CompileOptions (maybeDisableHelp h) is is2 ds es ep p (CompileBinary t fn o2 lf) f)       update _ = argError n "-o" "Requires an output name."+  parseSingle _ ((n,"-o"):_) = argError n "-o" "Set mode to binary (-m) first" -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"-i"):os) = update os where+  parseSingle (CompileOptions h is is2 ds es ep p m f) ((n,"-i"):os) = update os where     update ((n2,d):os2)       | isSuffixOf ".0rp" d = argError n2 d "Cannot directly include .0rp source files."       | isSuffixOf ".0rx" d = argError n2 d "Cannot directly include .0rx source files."       | isSuffixOf ".0rt" d = argError n2 d "Cannot directly include .0rt test files."       | otherwise = do           checkPathName n2 d "-i"-          return (os2,CompileOptions (maybeDisableHelp h) (is ++ [d]) is2 ds es ep ec p ex m o f)+          return (os2,CompileOptions (maybeDisableHelp h) (is ++ [d]) is2 ds es ep p m f)     update _ = argError n "-i" "Requires a source path." -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"-I"):os) = update os where+  parseSingle (CompileOptions h is is2 ds es ep p m f) ((n,"-I"):os) = update os where     update ((n2,d):os2)       | isSuffixOf ".0rp" d = argError n2 d "Cannot directly include .0rp source files."       | isSuffixOf ".0rx" d = argError n2 d "Cannot directly include .0rx source files."       | isSuffixOf ".0rt" d = argError n2 d "Cannot directly include .0rt test files."       | otherwise = do           checkPathName n2 d "-i"-          return (os2,CompileOptions (maybeDisableHelp h) is (is2 ++ [d]) ds es ep ec p ex m o f)+          return (os2,CompileOptions (maybeDisableHelp h) is (is2 ++ [d]) ds es ep p m f)     update _ = argError n "-I" "Requires a source path." -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"-e"):os) = update os where-    update ((n2,e):os2)-      | any (flip isSuffixOf e) allowedExtraTypes = do-          checkPathName n2 e "-e"-          return (os2,CompileOptions (maybeDisableHelp h) is is2 ds (es ++ [e]) ep ec p ex m o f)-      | takeExtension e == "" || e == "." = do-          checkPathName n2 e "-e"-          return (os2,CompileOptions (maybeDisableHelp h) is is2 ds es (ep ++ [e]) ec p ex m o f)-      | otherwise = argError n2 "-e" $ "Only " ++ intercalate ", " allowedExtraTypes ++-                                       " and directory sources are allowed."-    update _ = argError n "-e" "Requires a source filename."--  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,"-p"):os)+  parseSingle (CompileOptions h is is2 ds es ep p m f) ((n,"-p"):os)     | not $ null p = argError n "-p" "Path prefix already set."     | otherwise = update os where       update ((n2,p2):os2) = do         checkPathName n2 p2 "-p"-        return (os2,CompileOptions (maybeDisableHelp h) is is2 ds es ep ec p2 ex m o f)+        return (os2,CompileOptions (maybeDisableHelp h) is is2 ds es ep p2 m f)       update _ = argError n "-p" "Requires a path prefix."    parseSingle _ ((n,o@('-':_)):_) = argError n o "Unknown option." -  parseSingle (CompileOptions h is is2 ds es ep ec p ex m o f) ((n,d):os)+  parseSingle (CompileOptions h is is2 ds es ep p m f) ((n,d):os)       | isSuffixOf ".0rp" d = argError n d "Cannot directly include .0rp source files."       | isSuffixOf ".0rx" d = argError n d "Cannot directly include .0rx source files."       | isSuffixOf ".0rt" d = do@@ -205,39 +189,20 @@           argError n d "Test mode (-t) must be enabled before listing any .0rt test files."         checkPathName n d ""         let (ExecuteTests tp) = m-        return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep ec p ex (ExecuteTests $ tp ++ [d]) o f)+        return (os,CompileOptions (maybeDisableHelp h) is is2 ds es ep p (ExecuteTests $ tp ++ [d]) f)       | otherwise = do         checkPathName n d ""-        return (os,CompileOptions (maybeDisableHelp h) is is2 (ds ++ [d]) es ep ec p ex m o f)+        return (os,CompileOptions (maybeDisableHelp h) is is2 (ds ++ [d]) es ep p m f)  validateCompileOptions :: CompileErrorM m => CompileOptions -> m CompileOptions-validateCompileOptions co@(CompileOptions h is is2 ds es ep _ _ _ m o _)+validateCompileOptions co@(CompileOptions h is is2 ds _ _ _ m _)   | h /= HelpNotNeeded = return co -  | (not $ null o) && (isCompileIncremental m) =-    compileError "Output filename (-o) is not allowed in compile-only mode (-c)."--  | (not $ null o) && (isExecuteTests m) =-    compileError "Output filename (-o) is not allowed in test mode (-t)."   | (not $ null $ is ++ is2) && (isExecuteTests m) =     compileError "Include paths (-i/-I) are not allowed in test mode (-t)."-  | (not $ null $ es ++ ep) && (isExecuteTests m) =-    compileError "Extra files (-e) are not allowed in test mode (-t)." -  | (not $ null o) && (isCreateTemplates m) =-    compileError "Output filename (-o) is not allowed in template mode (--templates)."-  | (not $ null $ es ++ ep) && (isCreateTemplates m) =-    compileError "Extra files (-e) are not allowed in template mode (--templates)."--  | (not $ null o) && (isCompileRecompile m) =-    compileError "Output filename (-o) is not allowed in recompile mode (-r)."   | (not $ null $ is ++ is2) && (isCompileRecompile m) =     compileError "Include paths (-i/-I) are not allowed in recompile mode (-r)."-  | (not $ null $ es ++ ep) && (isCompileRecompile m) =-    compileError "Extra files (-e) are not allowed in recompile mode (-r)."--  | length ds > 1 && length (es ++ ep) > 0 =-    compileError "Extra files and paths (-e) cannot be used with multiple input paths, to avoid ambiguity."    | null ds =     compileError "Please specify at least one input path."
src/Cli/ParseMetadata.hs view
@@ -130,7 +130,6 @@     ns <-  parseRequired "namespace:"     parseNamespace     is <-  parseRequired "public_deps:"   (parseList parseQuoted)     is2 <- parseRequired "private_deps:"  (parseList parseQuoted)-    es <-  parseRequired "extra:"         (parseList readConfig)     cs <-  parseRequired "categories:"    (parseList parseCategoryName)     ds <-  parseRequired "subdirs:"       (parseList parseQuoted)     ps <-  parseRequired "public_files:"  (parseList parseQuoted)@@ -138,13 +137,13 @@     ts <-  parseRequired "test_files:"    (parseList parseQuoted)     hxx <- parseRequired "hxx_files:"     (parseList parseQuoted)     cxx <- parseRequired "cxx_files:"     (parseList parseQuoted)+    lf  <- parseRequired "link_flags:"    (parseList parseQuoted)     os <-  parseRequired "object_files:"  (parseList readConfig)-    return (CompileMetadata h p ns is is2 es cs ds ps xs ts hxx cxx os)+    return (CompileMetadata h p ns is is2 cs ds ps xs ts hxx cxx lf os)   writeConfig m = do     validateHash (cmVersionHash m)     validateNamespace (cmNamespace m)     _ <- collectAllOrErrorM $ map validateCategoryName (cmCategories m)-    extra   <- fmap concat $ collectAllOrErrorM $ map writeConfig $ cmExtraRequires m     objects <- fmap concat $ collectAllOrErrorM $ map writeConfig $ cmObjectFiles m     return $ [         "version_hash: " ++ (cmVersionHash m),@@ -156,9 +155,6 @@         "private_deps: ["       ] ++ indents (map show $ cmPrivateDeps m) ++ [         "]",-        "extra: ["-      ] ++ indents extra ++ [-        "]",         "categories: ["       ] ++ indents (cmCategories m) ++ [         "]",@@ -180,6 +176,9 @@         "cxx_files: ["       ] ++ indents (map show $ cmCxxFiles m) ++ [         "]",+        "link_flags: ["+      ] ++ indents (map show $ cmLinkFlags m) ++ [+        "]",         "object_files: ["       ] ++ indents objects ++ [         "]"@@ -254,20 +253,16 @@  instance ConfigFormat ModuleConfig where   readConfig = do-      p <-   parseOptional "root:"           "" parseQuoted-      d <-   parseRequired "path:"              parseQuoted-      is <-  parseOptional "public_deps:"    [] (parseList parseQuoted)-      is2 <- parseOptional "private_deps:"   [] (parseList parseQuoted)-      es <-  parseOptional "extra_files:"    [] (parseList parseQuoted)-      ep <-  parseOptional "extra_paths:"    [] (parseList parseQuoted)-      ec <-  parseOptional "always_include:" [] (parseList parseCategoryName)-      ex <-  parseOptional "external:"       [] (parseList parseCategoryName)-      m <-   parseRequired "mode:"              readConfig-      o <-   parseOptional "output:"         "" parseQuoted-      return (ModuleConfig p d is is2 es ep ec ex m o)+      p <-   parseOptional "root:"          "" parseQuoted+      d <-   parseRequired "path:"             parseQuoted+      is <-  parseOptional "public_deps:"   [] (parseList parseQuoted)+      is2 <- parseOptional "private_deps:"  [] (parseList parseQuoted)+      es <-  parseOptional "extra_files:"   [] (parseList readConfig)+      ep <-  parseOptional "include_paths:" [] (parseList parseQuoted)+      m <-   parseRequired "mode:"             readConfig+      return (ModuleConfig p d is is2 es ep m)   writeConfig m = do-    _ <- collectAllOrErrorM $ map validateCategoryName (rmExtraRequires m)-    _ <- collectAllOrErrorM $ map validateCategoryName (rmExternalDefs m)+    extra    <- fmap concat $ collectAllOrErrorM $ map writeConfig $ rmExtraFiles m     mode <- writeConfig (rmMode m)     return $ [         "root: " ++ show (rmRoot m),@@ -279,42 +274,78 @@       ] ++ indents (map show $ rmPrivateDeps m) ++ [         "]",         "extra_files: ["-      ] ++ indents (map show $ rmExtraFiles m) ++ [+      ] ++ indents extra ++ [         "]",-        "extra_paths: ["+        "include_paths: ["       ] ++ indents (map show $ rmExtraPaths m) ++ [-        "]",-        "always_include: ["-      ] ++ indents (rmExtraRequires m) ++ [-        "]",-        "external: ["-      ] ++ indents (rmExternalDefs m) ++ [         "]"-      ] ++ "mode: " `prependFirst` mode ++ output where-      output = if null (rmOutputName m)-                  then []-                  else ["output: " ++ show (rmOutputName m)]+      ] ++ "mode: " `prependFirst` mode +instance ConfigFormat ExtraSource where+  readConfig = category <|> other where+    category = do+      sepAfter (string_ "category_source")+      structOpen+      f <-  parseRequired "source:"        parseQuoted+      cs <- parseOptional "categories:" [] (parseList parseCategoryName)+      ds <- parseOptional "requires:"   [] (parseList parseCategoryName)+      structClose+      return (CategorySource f cs ds)+    other = do+      f <- parseQuoted+      return (OtherSource f)+  writeConfig (CategorySource f cs ds) = do+    _ <- collectAllOrErrorM $ map validateCategoryName cs+    _ <- collectAllOrErrorM $ map validateCategoryName ds+    return $ [+        "category_source {",+        indent ("source: " ++ show f),+        indent "categories: ["+      ] ++ (indents . indents) cs ++ [+        indent "]",+        indent "requires: ["+      ] ++ (indents . indents) ds ++ [+        indent "]",+        "}"+      ]+  writeConfig (OtherSource f) = return [show f]+ instance ConfigFormat CompileMode where   readConfig = labeled "compile mode" $ binary <|> incremental where     binary = do       sepAfter (string_ "binary")       structOpen-      c <- parseRequired "category:" parseCategoryName-      f <- parseRequired "function:" parseFunctionName+      c <-  parseRequired "category:"      parseCategoryName+      f <-  parseRequired "function:"      parseFunctionName+      o <-  parseOptional "output:"     "" parseQuoted+      lf <- parseOptional "link_flags:" [] (parseList parseQuoted)       structClose-      return (CompileBinary c f)+      return (CompileBinary c f o lf)     incremental = do       sepAfter (string_ "incremental")-      return CompileIncremental-  writeConfig (CompileBinary c f) = do+      structOpen+      lf <- parseOptional "link_flags:" [] (parseList parseQuoted)+      structClose+      return (CompileIncremental lf)+  writeConfig (CompileBinary c f o lf) = do     validateCategoryName c     validateFunctionName f     return $ [         "binary {",         indent ("category: " ++ c),         indent ("function: " ++ f),+        indent ("output: " ++ show o),+        indent ("link_flags: [")+      ] ++ (indents . indents) (map show lf) ++ [+        indent "]",         "}"       ]-  writeConfig CompileIncremental = return ["incremental"]+  writeConfig (CompileIncremental lf) = do+    return $ [+        "incremental {",+        indent ("link_flags: [")+      ] ++ (indents . indents) (map show lf) ++ [+        indent "]",+        "}"+      ]   writeConfig _ = compileError "Invalid compile mode"
src/Cli/ProcessMetadata.hs view
@@ -25,11 +25,11 @@   getCachedPath,   getCacheRelativePath,   getIncludePathsForDeps,+  getLinkFlagsForDeps,   getNamespacesForDeps,   getObjectFilesForDeps,   getObjectFileResolver,   getRealPathsForDeps,-  getRequiresFromDeps,   getSourceFilesForDeps,   isPathConfigured,   isPathUpToDate,@@ -149,6 +149,7 @@ writeRecompile :: String -> ModuleConfig -> IO () writeRecompile p m = do   p' <- canonicalizePath p+  let f = p </> recompileFilename   hPutStrLn stderr $ "Updating config for \"" ++ p' ++ "\"."   let m' = autoWriteConfig m   if isCompileError m'@@ -156,7 +157,10 @@        hPutStrLn stderr $ "Could not serialize module config."        hPutStrLn stderr $ show (getCompileError m')        exitFailure-     else writeFile (p </> recompileFilename) (getCompileSuccess m')+     else do+       exists <- doesFileExist f+       when exists $ removeFile f+       writeFile f (getCompileSuccess m')  eraseCachedData :: String -> IO () eraseCachedData p = do@@ -206,15 +210,15 @@ getSourceFilesForDeps = concat . map extract where   extract m = map (cmPath m </>) (cmPublicFiles m) -getRequiresFromDeps :: [CompileMetadata] -> [CategoryIdentifier]-getRequiresFromDeps = concat . map cmExtraRequires- getNamespacesForDeps :: [CompileMetadata] -> [String] getNamespacesForDeps = filter (not . null) . map cmNamespace  getIncludePathsForDeps :: [CompileMetadata] -> [String] getIncludePathsForDeps = concat . map cmSubdirs +getLinkFlagsForDeps :: [CompileMetadata] -> [String]+getLinkFlagsForDeps = concat . map cmLinkFlags+ getObjectFilesForDeps :: [CompileMetadata] -> [ObjectFile] getObjectFilesForDeps = concat . map cmObjectFiles @@ -241,7 +245,7 @@     | otherwise = do         when (not s) $ hPutStrLn stderr $ "Loading metadata for dependency \"" ++ p ++ "\"."         m <- loadMetadata p-        fresh <- checkModuleFreshness p m+        fresh <- checkModuleFreshness s p m         when (not s && not fresh) $           hPutStrLn stderr $ "Module \"" ++ p ++ "\" is out of date and should be recompiled."         let sameVersion = checkModuleVersionHash h m@@ -277,8 +281,8 @@ checkModuleVersionHash :: String -> CompileMetadata -> Bool checkModuleVersionHash h m = cmVersionHash m == h -checkModuleFreshness :: String -> CompileMetadata -> IO Bool-checkModuleFreshness p (CompileMetadata _ p2 _ is is2 _ _ _ ps xs ts hxx cxx _) = do+checkModuleFreshness :: Bool -> String -> CompileMetadata -> IO Bool+checkModuleFreshness s p (CompileMetadata _ p2 _ is is2 _ _ ps xs ts hxx cxx _ _) = do   time <- getModificationTime $ getCachedPath p "" metadataFilename   (ps2,xs2,ts2) <- findSourceFiles p ""   let e1 = checkMissing ps ps2@@ -293,10 +297,16 @@     check time f = do       exists <- doesFileOrDirExist f       if not exists-         then return True+         then do+           when (not s) $ hPutStrLn stderr $ "Required path \"" ++ f ++ "\" is missing."+           return True          else do            time2 <- getModificationTime f-           return (time2 > time)+           if time2 > time+              then do+                when (not s) $ hPutStrLn stderr $ "Required path \"" ++ f ++ "\" is out of date."+                return True+              else return False     checkMissing s0 s1 = not $ null $ (Set.fromList s1) `Set.difference` (Set.fromList s0)     doesFileOrDirExist f2 = do       existF <- doesFileExist f2@@ -304,8 +314,8 @@         then return True         else doesDirectoryExist f2 -getObjectFileResolver :: [CategoryIdentifier] -> [ObjectFile] -> [Namespace] -> [CategoryName] -> [String]-getObjectFileResolver ce os ns ds = resolved ++ nonCategories where+getObjectFileResolver :: [ObjectFile] -> [Namespace] -> [CategoryName] -> [String]+getObjectFileResolver os ns ds = resolved ++ nonCategories where   categories    = filter isCategoryObjectFile os   nonCategories = map oofFile $ filter (not . isCategoryObjectFile) os   categoryMap = Map.fromList $ map keyByCategory2 categories@@ -313,7 +323,7 @@   objectMap = Map.fromList $ map keyBySpec categories   keyBySpec o = (cofCategory o,o)   directDeps = concat $ map (resolveDep2 . show) ds-  directResolved = map cofCategory directDeps ++ ce+  directResolved = map cofCategory directDeps   resolveDep2 d = unwrap $ foldl (<|>) Nothing allChecks <|> Just [] where     allChecks = map (\n -> (d,n) `Map.lookup` categoryMap >>= return . (:[])) (map show ns ++ [""])     unwrap (Just xs) = xs
src/Cli/TestRunner.hs view
@@ -158,11 +158,11 @@       let main   = dir </> "testcase.cpp"       let binary = dir </> "testcase"       writeFile main $ concat $ map (++ "\n") c+      let lf = getLinkFlagsForDeps deps       let paths' = nub $ map fixPath (dir:paths)-      let req2 = getRequiresFromDeps deps-      let ofr = getObjectFileResolver req2 (sources' ++ os)+      let ofr = getObjectFileResolver (sources' ++ os)       let os' = ofr ns req-      let command = CompileToBinary main os' binary paths'+      let command = CompileToBinary main os' binary paths' lf       runCxxCommand b command     writeSingleFile d ca@(CxxOutput _ f2 _ _ _ content) = do       writeFile (d </> f2) $ concat $ map (++ "\n") content
src/CompilerCxx/Category.hs view
@@ -84,7 +84,7 @@ compileCategoryModule :: (Show c, CompileErrorM m, MergeableM m) =>   CategoryModule c -> m [CxxOutput] compileCategoryModule (CategoryModule tm ns cs xa ex) = do-  checkSupefluous $ Set.toList $ es `Set.difference` ca+  checkSupefluous $ Set.toList $ (Set.fromList ex) `Set.difference` ca   tm' <- includeNewTypes tm cs   hxx <- collectAllOrErrorM $ map (compileCategoryDeclaration tm' ns) cs   let interfaces = filter (not . isValueConcrete) cs@@ -92,26 +92,33 @@   xa2 <- collectAllOrErrorM $ map (compileInternal ns) xa   let xx = concat $ map snd xa2   let dm = mapByName $ concat $ map fst xa2-  checkDefined dm $ filter isValueConcrete cs+  checkDefined dm ex $ filter isValueConcrete cs   return $ hxx ++ cxx ++ xx where     compileInternal ns0 (PrivateSource ns1 cs2 ds) = do       let cs' = cs++cs2+      checkLocals ds (ex ++ map (show . getCategoryName) cs')+      let dm = mapByName ds+      checkDefined dm [] $ filter isValueConcrete cs2       tm' <- includeNewTypes tm cs'       hxx <- collectAllOrErrorM $ map (compileCategoryDeclaration tm' ns0) cs2       let interfaces = filter (not . isValueConcrete) cs2       cxx1 <- collectAllOrErrorM $ map compileInterfaceDefinition interfaces       cxx2 <- collectAllOrErrorM $ map (compileDefinition tm' (ns1:ns)) ds-      let dm = mapByName ds-      checkDefined dm $ filter isValueConcrete cs2       return (ds,hxx ++ cxx1 ++ cxx2)     compileDefinition tm2 ns2 d = do       tm2' <- mergeInternalInheritance tm2 d       compileConcreteDefinition tm2' ns2 d     mapByName = Map.fromListWith (++) . map (\d -> (dcName d,[d]))     ca = Set.fromList $ map (show . getCategoryName) $ filter isValueConcrete cs-    es = Set.fromList ex-    checkDefined dm = mergeAllM . map (checkSingle dm)-    checkSingle dm t =+    checkLocals ds cs2 = mergeAllM $ map (checkLocal $ Set.fromList cs2) ds+    checkLocal cs2 d =+      if (show $ dcName d) `Set.member` cs2+         then return ()+         else compileError ("Definition for " ++ show (dcName d) +++                            formatFullContextBrace (dcContext d) +++                            " does not correspond to a category in this module")+    checkDefined dm ex2 = mergeAllM . map (checkSingle dm (Set.fromList ex2))+    checkSingle dm es t =       case ((show $ getCategoryName t) `Set.member` es, getCategoryName t `Map.lookup` dm) of            (False,Just [_]) -> return ()            (True,Nothing)   -> return ()@@ -158,7 +165,7 @@                      (headerFilename name)                      (getCategoryNamespace t)                      (ns ++ [getCategoryNamespace t])-                     (filter (not . isBuiltinCategory) $ Set.toList $ cdRequired file)+                     (Set.toList $ cdRequired file)                      (cdOutput file) where     file = mergeAll $ [         CompiledData depends [],@@ -389,18 +396,18 @@ commonDefineAll t ns top bottom ce te fe = do   let filename = sourceFilename name   (CompiledData req out) <- fmap (addNamespace t) $ mergeAllM $ [-      return $ CompiledData (Set.fromList [name]) [],+      return $ CompiledData (Set.fromList (name:getCategoryMentions t)) [],       return $ mergeAll [createCollection,createAllLabels]     ] ++ conditionalContent   let inherited = Set.fromList $ (map (tiName . vrType) $ getCategoryRefines t) ++                                  (map (diName . vdType) $ getCategoryDefines t)   let includes = map (\i -> "#include \"" ++ headerFilename i ++ "\"") $-                   filter (not . isBuiltinCategory) $ Set.toList $ Set.union req inherited+                   Set.toList $ Set.union req inherited   return $ CxxOutput (Just $ getCategoryName t)                      filename                      (getCategoryNamespace t)                      ((getCategoryNamespace t):ns)-                     (filter (not . isBuiltinCategory) $ Set.toList req)+                     (Set.toList req)                      (baseSourceIncludes ++ includes ++ out)   where     conditionalContent@@ -686,7 +693,7 @@       "  " ++ startFunctionTracing n     ] ++ out ++ ["}"] where       depIncludes req2 = map (\i -> "#include \"" ++ headerFilename i ++ "\"") $-                           filter (not . isBuiltinCategory) $ Set.toList req2+                           Set.toList req2  createMainFile :: (Show c, CompileErrorM m, MergeableM m) =>   CategoryMap c -> CategoryName -> FunctionName -> m (Namespace,[String])@@ -704,4 +711,20 @@ createTestFile tm e = flip reviseError ("In the creation of the test binary procedure") $ do   ca@(CompiledData req _) <- fmap indentCompiled (compileMainProcedure tm e)   let file = createMainCommon "main" ca-  return (filter (not . isBuiltinCategory) $ Set.toList req,file)+  return (Set.toList req,file)++getCategoryMentions :: AnyCategory c -> [CategoryName]+getCategoryMentions t = fromRefines (getCategoryRefines t) +++                        fromDefines (getCategoryDefines t) +++                        fromFunctions (getCategoryFunctions t) +++                        fromFilters (getCategoryFilters t) where+  fromRefines rs = fromGenerals $ map (SingleType . JustTypeInstance . vrType) rs+  fromDefines ds = concat $ map (fromDefine . 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+  fromFilters fs = concat $ map (fromFilter . pfFilter) fs+  fromFilter (TypeFilter _ t2)  = Set.toList $ categoriesFromTypes $ SingleType t2+  fromFilter (DefinesFilter t2) = fromDefine t2+  fromGenerals = Set.toList . Set.unions . map categoriesFromTypes
src/CompilerCxx/Procedure.hs view
@@ -22,6 +22,7 @@ {-# LANGUAGE Safe #-}  module CompilerCxx.Procedure (+  categoriesFromTypes,   compileExecutableProcedure,   compileMainProcedure,   compileExpression,@@ -189,6 +190,7 @@        _ -> return ()   csWrite $ ["{"] ++ lsUpdate loop ++ ["}","continue;"] compileStatement (FailCall c e) = do+  csRequiresTypes (Set.fromList [BuiltinFormatted,BuiltinString])   e' <- compileExpression e   when (length (pValues $ fst e') /= 1) $     lift $ compileError $ "Expected single return in argument" ++ formatFullContextBrace c@@ -199,7 +201,7 @@     ("In fail call at " ++ formatFullContext c)   csSetNoReturn   csWrite $ setTraceContext c-  csWrite ["BuiltinFail(" ++ useAsUnwrapped e0 ++ ");"]+  csWrite ["BUILTIN_FAIL(" ++ useAsUnwrapped e0 ++ ")"] compileStatement (IgnoreValues c e) = do   (_,e') <- compileExpression e   csWrite $ setTraceContext c@@ -416,26 +418,33 @@   Expression c -> CompilerState a m (ExpressionType,ExprValue) compileExpression = compile where   compile (Literal (StringLiteral _ l)) = do+    csRequiresTypes (Set.fromList [BuiltinString])     return (Positional [stringRequiredValue],UnboxedPrimitive PrimString $ "PrimString_FromLiteral(" ++ escapeChars l ++ ")")   compile (Literal (CharLiteral _ l)) = do+    csRequiresTypes (Set.fromList [BuiltinChar])     return (Positional [charRequiredValue],UnboxedPrimitive PrimChar $ "PrimChar('" ++ escapeChar l ++ "')")   compile (Literal (IntegerLiteral c True l)) = do+    csRequiresTypes (Set.fromList [BuiltinInt])     when (l > 2^(64 :: Integer) - 1) $ lift $ compileError $       "Literal " ++ show l ++ formatFullContextBrace c ++ " is greater than the max value for 64-bit unsigned"     let l' = if l > 2^(63 :: Integer) - 1 then l - 2^(64 :: Integer) else l     return (Positional [intRequiredValue],UnboxedPrimitive PrimInt $ "PrimInt(" ++ show l' ++ ")")   compile (Literal (IntegerLiteral c False l)) = do+    csRequiresTypes (Set.fromList [BuiltinInt])     when (l > 2^(63 :: Integer) - 1) $ lift $ compileError $       "Literal " ++ show l ++ formatFullContextBrace c ++ " is greater than the max value for 64-bit signed"     when ((-l) > (2^(63 :: Integer) - 2)) $ lift $ compileError $       "Literal " ++ show l ++ formatFullContextBrace c ++ " is less than the min value for 64-bit signed"     return (Positional [intRequiredValue],UnboxedPrimitive PrimInt $ "PrimInt(" ++ show l ++ ")")   compile (Literal (DecimalLiteral _ l e)) = do+    csRequiresTypes (Set.fromList [BuiltinFloat])     -- TODO: Check bounds.     return (Positional [floatRequiredValue],UnboxedPrimitive PrimFloat $ "PrimFloat(" ++ show l ++ "E" ++ show e ++ ")")   compile (Literal (BoolLiteral _ True)) = do+    csRequiresTypes (Set.fromList [BuiltinBool])     return (Positional [boolRequiredValue],UnboxedPrimitive PrimBool "true")   compile (Literal (BoolLiteral _ False)) = do+    csRequiresTypes (Set.fromList [BuiltinBool])     return (Positional [boolRequiredValue],UnboxedPrimitive PrimBool "false")   compile (Literal (EmptyLiteral _)) = do     return (Positional [emptyValue],UnwrappedSingle "Var_empty")@@ -641,6 +650,7 @@       return f' -- TODO: Compile BuiltinCall like regular functions, for consistent validation. compileExpressionStart (BuiltinCall c (FunctionCall _ BuiltinPresent ps es)) = do+  csRequiresTypes (Set.fromList [BuiltinBool])   when (length (pValues ps) /= 0) $     lift $ compileError $ "Expected 0 type parameters" ++ formatFullContextBrace c   when (length (pValues es) /= 1) $
src/Config/LoadConfig.hs view
@@ -108,12 +108,12 @@       nsFlag         | null ns = []         | otherwise = ["-D" ++ nm ++ "=" ++ ns]-  runCxxCommand (UnixBackend cb co _) (CompileToBinary m ss o ps) = do+  runCxxCommand (UnixBackend cb co _) (CompileToBinary m ss o ps lf) = do     let arFiles    = filter (isSuffixOf ".a")       ss     let otherFiles = filter (not . isSuffixOf ".a") ss     executeProcess cb $ co ++ otherOptions ++ m:otherFiles ++ arFiles ++ ["-o", o]     return o where-      otherOptions = map ("-I" ++) $ map normalise ps+      otherOptions = lf ++ map ("-I" ++) (map normalise ps)   runTestCommand _ (TestCommand b p) = do     (outF,outH) <- mkstemps "/tmp/ztest_" ".txt"     (errF,errH) <- mkstemps "/tmp/ztest_" ".txt"
src/Config/Programs.hs view
@@ -44,7 +44,8 @@     ctbMain :: String,     ctbSources :: [String],     ctbOutput :: String,-    ctoPaths :: [String]+    ctbPaths :: [String],+    ctbLinkFlags :: [String]   }   deriving (Show) 
src/Test/ParseMetadata.hs view
@@ -41,16 +41,6 @@         "/home/project/private-dep1",         "/home/project/private-dep2"       ],-      cmExtraRequires = [-        CategoryIdentifier {-          ciPath = "/home/project/private-dep1",-          ciCategory = "PrivateCategory",-          ciNamespace = "private_123456"-        },-        UnresolvedCategory {-          ucCategory = "UnresolvedCategory"-        }-      ],       cmCategories = [         "MyCategory",         "MyOtherCategory"@@ -79,6 +69,10 @@         "/home/project/special/category1.cpp",         "/home/project/special/category2.cpp"       ],+      cmLinkFlags = [+        "-lm",+        "-ldl"+      ],       cmObjectFiles = [         CategoryObjectFile {           cofCategory = CategoryIdentifier {@@ -110,7 +104,6 @@       cmNamespace = "public_ABCDEF",       cmPublicDeps = [],       cmPrivateDeps = [],-      cmExtraRequires = [],       cmCategories = [],       cmSubdirs = [],       cmPublicFiles = [],@@ -118,6 +111,7 @@       cmTestFiles = [],       cmHxxFiles = [],       cmCxxFiles = [],+      cmLinkFlags = [],       cmObjectFiles = []     }, @@ -127,7 +121,6 @@       cmNamespace = "bad namespace",       cmPublicDeps = [],       cmPrivateDeps = [],-      cmExtraRequires = [],       cmCategories = [],       cmSubdirs = [],       cmPublicFiles = [],@@ -135,6 +128,7 @@       cmTestFiles = [],       cmHxxFiles = [],       cmCxxFiles = [],+      cmLinkFlags = [],       cmObjectFiles = []     }, @@ -144,7 +138,6 @@       cmNamespace = "public_ABCDEF",       cmPublicDeps = [],       cmPrivateDeps = [],-      cmExtraRequires = [],       cmCategories = [         "bad category"       ],@@ -154,6 +147,7 @@       cmTestFiles = [],       cmHxxFiles = [],       cmCxxFiles = [],+      cmLinkFlags = [],       cmObjectFiles = []     }, @@ -169,53 +163,47 @@         "/home/project/private-dep2"       ],       rmExtraFiles = [-        "extra1.cpp",-        "extra2.cpp"+        CategorySource {+          csSource = "extra1.cpp",+          csCategories = [+            "Category1",+            "Category2"+          ],+          csDepCategories = [+            "DepCategory1",+            "DepCategory2"+          ]+        },+        OtherSource {+          osSource = "extra2.cpp"+        }       ],       rmExtraPaths = [         "extra1",         "extra2"       ],-      rmExtraRequires = [-        "Extra1",-        "Extra2"-      ],-      rmExternalDefs = [-        "External1",-        "External1"-      ],-      rmMode = CompileIncremental,-      rmOutputName = "binary"+      rmMode = CompileIncremental {+        ciLinkFlags = [+          "-lm",+          "-ldl"+        ]+      }     }, -    checkWriteFail "bad category" $ ModuleConfig {-      rmRoot = "/home/projects",-      rmPath = "special",-      rmPublicDeps = [],-      rmPrivateDeps = [],-      rmExtraFiles = [],-      rmExtraPaths = [],-      rmExtraRequires = [+    checkWriteFail "bad category" $ CategorySource {+      csSource = "extra1.cpp",+      csCategories = [         "bad category"       ],-      rmExternalDefs = [],-      rmMode = CompileIncremental,-      rmOutputName = ""+      csDepCategories = []     }, -    checkWriteFail "bad category" $ ModuleConfig {-      rmRoot = "/home/projects",-      rmPath = "special",-      rmPublicDeps = [],-      rmPrivateDeps = [],-      rmExtraFiles = [],-      rmExtraPaths = [],-      rmExtraRequires = [],-      rmExternalDefs = [+    checkWriteFail "bad category" $ CategorySource {+      csSource = "extra1.cpp",+      csCategories = [],+      csDepCategories = [         "bad category"-      ],-      rmMode = CompileIncremental,-      rmOutputName = ""+      ]     },      checkWriteFail "bad category" $ CategoryIdentifier {@@ -236,20 +224,31 @@      checkWriteThenRead $ CompileBinary {       cbCategory = "SpecialCategory",-      cbFunction = "specialFunction"+      cbFunction = "specialFunction",+      cbOutputName = "binary",+      cbLinkFlags = []     },      checkWriteFail "bad category" $ CompileBinary {       cbCategory = "bad category",-      cbFunction = "specialFunction"+      cbFunction = "specialFunction",+      cbOutputName = "binary",+      cbLinkFlags = []     },      checkWriteFail "bad function" $ CompileBinary {       cbCategory = "SpecialCategory",-      cbFunction = "bad function"+      cbFunction = "bad function",+      cbOutputName = "binary",+      cbLinkFlags = []     }, -    checkWriteThenRead $ CompileIncremental,+    checkWriteThenRead $ CompileIncremental {+      ciLinkFlags = [+        "-lm",+        "-ldl"+      ]+    },      checkWriteFail "compile mode" $ ExecuteTests { etInclude = [] },     checkWriteFail "compile mode" $ CompileRecompile,@@ -260,7 +259,7 @@ checkWriteThenRead :: (Eq a, Show a, ConfigFormat a) => a -> IO (CompileInfo ()) checkWriteThenRead m = return $ do   text <- fmap spamComments $ autoWriteConfig m-  m' <- autoReadConfig "(string)" text+  m' <- autoReadConfig "(string)" text `reviseError` ("Serialized >>>\n\n" ++ text ++ "\n<<< Serialized\n\n")   when (m' /= m) $     compileError $ "Failed to match after write/read\n" ++                    "Before:\n" ++ show m ++ "\n" ++
tests/.zeolite-module view
@@ -4,4 +4,4 @@   "visibility"   "visibility2" ]-mode: incremental+mode: incremental {}
tests/check-defs/.zeolite-module view
@@ -1,6 +1,3 @@ root: "../.." path: "tests/check-defs"-external: [-  External-]-mode: incremental+mode: incremental {}
tests/check-defs/public.0rp view
@@ -19,5 +19,3 @@ concrete Type {}  concrete Undefined {}--concrete External {}
tests/function-merging.0rt view
@@ -141,6 +141,16 @@   @value call () -> (Interface) } +define Value {+  create () {+    return Value{}+  }++  call () {+    return self+  }+}+ define Test {   run () {} }
tests/simple.0rt view
@@ -71,3 +71,14 @@ testcase "minimal linking works properly" {   success empty }+++testcase "attempt to define outside of this module" {+  error+  require "String"+  require "module"+  exclude "procedure definition"+}++// The declaration for String is in scope, but it lives outside of this module.+define String {}
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 {}
zeolite-lang.cabal view
@@ -1,7 +1,7 @@ cabal-version:       2.2  name:                zeolite-lang-version:             0.3.0.0+version:             0.4.0.0 synopsis:            Zeolite is a statically-typed, general-purpose programming language.  description:@@ -59,16 +59,16 @@                      GHC == 8.2.2,                      GHC == 8.0.2 -extra-source-files:  ChangeLog.md-extra-source-files:  src/Test/testfiles/*.0rt,+extra-source-files:  ChangeLog.md,+                     src/Test/testfiles/*.0rt,                      src/Test/testfiles/*.0rx  data-files:          base/.zeolite-module,                      base/*.0rp,+                     base/*.cc,                      base/*.cpp,                      base/*.hpp,-                     capture-thread/include/*.h,-                     capture-thread/src/*.cc,+                     base/*.h,                      example/hello/README.md,                      example/hello/*.0rx,                      example/regex/README.md,