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 +17/−0
- base/.zeolite-module +24/−33
- base/Category_Bool.cpp +214/−0
- base/Category_Char.cpp +250/−0
- base/Category_Float.cpp +231/−0
- base/Category_Int.cpp +250/−0
- base/Category_String.cpp +245/−0
- base/builtin.0rp +17/−17
- base/builtin.cpp +0/−1192
- base/builtin.hpp +0/−41
- base/category-header.hpp +8/−0
- base/category-source.cpp +104/−1
- base/category-source.hpp +15/−1
- base/thread-capture.h +217/−0
- base/thread-crosser.cc +33/−0
- base/thread-crosser.h +254/−0
- bin/zeolite-setup.hs +0/−3
- capture-thread/include/thread-capture.h +0/−217
- capture-thread/include/thread-crosser.h +0/−254
- capture-thread/src/thread-crosser.cc +0/−33
- lib/file/.zeolite-module +9/−7
- lib/util/.zeolite-module +13/−9
- src/Cli/CompileMetadata.hs +3/−6
- src/Cli/CompileOptions.hs +44/−13
- src/Cli/Compiler.hs +71/−73
- src/Cli/ParseCompileOptions.hs +28/−63
- src/Cli/ParseMetadata.hs +68/−37
- src/Cli/ProcessMetadata.hs +23/−13
- src/Cli/TestRunner.hs +3/−3
- src/CompilerCxx/Category.hs +36/−13
- src/CompilerCxx/Procedure.hs +11/−1
- src/Config/LoadConfig.hs +2/−2
- src/Config/Programs.hs +2/−1
- src/Test/ParseMetadata.hs +52/−53
- tests/.zeolite-module +1/−1
- tests/check-defs/.zeolite-module +1/−4
- tests/check-defs/public.0rp +0/−2
- tests/function-merging.0rt +10/−0
- tests/simple.0rt +11/−0
- tests/visibility/.zeolite-module +1/−1
- tests/visibility/internal/.zeolite-module +1/−1
- tests/visibility2/.zeolite-module +1/−1
- tests/visibility2/internal/.zeolite-module +1/−1
- zeolite-lang.cabal +5/−5
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,