1 // Copyright 2016-2021 Doug Moen 2 // Licensed under the Apache License, version 2.0 3 // See accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0 4 5 #ifndef LIBCURV_SYSTEM_H 6 #define LIBCURV_SYSTEM_H 7 8 #include <ostream> 9 #include <unordered_set> 10 #include <map> 11 #include <libcurv/filesystem.h> 12 #include <libcurv/builtin.h> 13 14 namespace curv { 15 16 struct Context; 17 struct Program; 18 19 /// An abstract interface to the client and operating system. 20 /// 21 /// The System object is owned by the client, who is responsible for ensuring 22 /// that it exists for as long as references to it might exist in Curv 23 /// data structures. 24 struct System 25 { 26 /// This is the set of standard or builtin bindings 27 /// used by the `file` primitive to interpret Curv source files. 28 virtual const Namespace& std_namespace() = 0; 29 30 // Set by the `-v` command line argument. 31 bool verbose_ = false; 32 33 // Deprecation level (0, 1 or 2) for deprecation warnings. 34 // Set by the `--depr=N` command line argument. 35 int depr_ = 1; 36 37 // Set to true if you want coloured text to be written on the console. 38 bool use_colour_ = false; 39 40 // True if the json-api protocol is being used. 41 bool use_json_api_ = false; 42 43 virtual std::ostream& console() = 0; 44 45 // Write an exception object to an output stream, using the Curv colour 46 // scheme if use_colour is true. Special behaviour for curv::Exception. 47 // This static function is handy for printing an exception caught during 48 // the construction of a System object (otherwise, use System::message). 49 static void print_exception( 50 const char* prefix, const std::exception& exc, 51 std::ostream& out, bool use_colour = false); 52 53 static void print_json_exception( 54 const char* type, const std::exception& exc, std::ostream& out); 55 56 void error(const std::exception& exc); 57 void warning(const std::exception& exc); 58 void print(const char*); 59 60 // This is non-empty while a `file` operation is being evaluated. 61 // It is used to detect recursive file references. 62 // Later, this may change to a file cache. 63 // Or, it could move into the Program structure. 64 std::unordered_set<Filesystem::path,Path_Hash> active_files_{}; 65 66 // Used by `file` to import a file based on its extension. 67 // The extension includes the leading '.', and "" means no extension. 68 // The extension is converted to lowercase on all platforms. 69 using Importer = void (*)(const Filesystem::path&, Program&, const Context&); 70 std::map<std::string,Importer> importers_; 71 }; 72 73 // RAII helper class, for use with System::active_files_. 74 struct Active_File 75 { 76 std::unordered_set<Filesystem::path,Path_Hash>& active_files_; 77 Filesystem::path& file_; Active_FileActive_File78 Active_File( 79 std::unordered_set<Filesystem::path,Path_Hash>& af, 80 Filesystem::path& f) 81 : 82 active_files_(af), 83 file_(f) 84 { 85 active_files_.insert(file_); 86 } ~Active_FileActive_File87 ~Active_File() 88 { 89 active_files_.erase(file_); 90 } 91 }; 92 93 /// Default implementation of the System interface. 94 struct System_Impl : public System 95 { 96 Namespace std_namespace_; 97 std::ostream& console_; 98 System_Impl(std::ostream&); 99 void load_library(String_Ref path); 100 virtual const Namespace& std_namespace() override; 101 virtual std::ostream& console() override; 102 }; 103 104 } // namespace curv 105 #endif // header guard 106